Skip to content

Commit

Permalink
chore: update effect (#495)
Browse files Browse the repository at this point in the history
* feat: response object

* chore: update effect
sukovanej authored Mar 22, 2024
1 parent 8f16bef commit c765639
Showing 10 changed files with 240 additions and 191 deletions.
6 changes: 6 additions & 0 deletions .changeset/orange-geckos-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"effect-http-node": patch
"effect-http": patch
---

Update effect.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -27,11 +27,11 @@
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.1",
"@effect/build-utils": "^0.7.6",
"@effect/docgen": "^0.3.8",
"@effect/dtslint": "^0.0.5",
"@effect/docgen": "^0.4.0",
"@effect/dtslint": "^0.1.0",
"@effect/eslint-plugin": "^0.1.2",
"@effect/language-service": "^0.1.0",
"@effect/vitest": "^0.1.0",
"@effect/vitest": "^0.1.1",
"@types/node": "^20.11.30",
"@types/swagger-ui-dist": "^3.30.4",
"@typescript-eslint/eslint-plugin": "^7.3.1",
@@ -40,7 +40,7 @@
"babel-plugin-annotate-pure-calls": "^0.4.0",
"eslint": "^8.57.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-codegen": "0.27.0",
"eslint-plugin-codegen": "0.28.0",
"eslint-plugin-deprecation": "^2.0.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-simple-import-sort": "^12.0.0",
20 changes: 10 additions & 10 deletions packages/effect-http-node/package.json
Original file line number Diff line number Diff line change
@@ -32,20 +32,20 @@
"swagger-ui-dist": "^5.12.0"
},
"peerDependencies": {
"@effect/platform": "^0.48.14",
"@effect/platform-node": "^0.45.16",
"@effect/schema": "^0.64.10",
"effect": "^2.4.10",
"@effect/platform": "^0.48.15",
"@effect/platform-node": "^0.45.17",
"@effect/schema": "^0.64.11",
"effect": "^2.4.11",
"effect-http": "workspace:^"
},
"devDependencies": {
"@effect/platform": "^0.48.14",
"@effect/platform-bun": "^0.32.27",
"@effect/platform-node": "^0.45.16",
"@effect/schema": "^0.64.10",
"@effect/platform": "^0.48.15",
"@effect/platform-bun": "^0.32.28",
"@effect/platform-node": "^0.45.17",
"@effect/schema": "^0.64.11",
"@types/node": "^20.11.30",
"effect": "^2.4.10",
"effect": "^2.4.11",
"effect-http": "workspace:^",
"effect-log": "^0.30.11"
"effect-log": "^0.30.12"
}
}
38 changes: 37 additions & 1 deletion packages/effect-http-node/test/client.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { HttpServer } from "@effect/platform"
import { Schema } from "@effect/schema"
import * as it from "@effect/vitest"
import { Cause, Duration, Effect, Exit, Fiber, pipe } from "effect"
import { Cause, Duration, Effect, Either, Exit, Fiber, Match, pipe } from "effect"
import { Api, ClientError, ExampleServer, RouterBuilder } from "effect-http"
import { NodeTesting } from "effect-http-node"
import { expect, test, vi } from "vitest"
@@ -239,3 +239,39 @@ it.scoped(
expect(result.message).toEqual("validation error")
})
)

it.scoped(
"multiple responses",
Effect.gen(function*(_) {
const api = pipe(
Api.make(),
Api.addEndpoint(
pipe(
Api.get("test", "/test"),
Api.setResponse({ status: 200, body: Schema.string }),
Api.addResponse({ status: 201, body: Schema.number }),
Api.addResponse({ status: 400, body: Schema.string }),
Api.addResponse({ status: 422, body: Schema.string })
)
)
)

const app = ExampleServer.make(api).pipe(RouterBuilder.build)

const result = yield* _(
NodeTesting.make(app, api),
Effect.flatMap((client) => client.test({})),
Effect.either
)

const r = Either.isRight(result) ?
Match.value(result.right).pipe(
Match.when({ status: 200 }, ({ body }) => body),
Match.when({ status: 201 }, ({ body }) => body.toString()),
Match.exhaustive
) :
"nope"

expect(typeof r).toBe("string")
})
)
14 changes: 7 additions & 7 deletions packages/effect-http/package.json
Original file line number Diff line number Diff line change
@@ -30,16 +30,16 @@
"coverage": "vitest --coverage"
},
"dependencies": {
"schema-openapi": "^0.33.6"
"schema-openapi": "^0.33.7"
},
"peerDependencies": {
"@effect/platform": "^0.48.14",
"@effect/schema": "^0.64.10",
"effect": "^2.4.10"
"@effect/platform": "^0.48.15",
"@effect/schema": "^0.64.11",
"effect": "^2.4.11"
},
"devDependencies": {
"@effect/platform": "^0.48.14",
"@effect/schema": "^0.64.10",
"effect": "^2.4.10"
"@effect/platform": "^0.48.15",
"@effect/schema": "^0.64.11",
"effect": "^2.4.11"
}
}
62 changes: 32 additions & 30 deletions packages/effect-http/src/ApiEndpoint.ts
Original file line number Diff line number Diff line change
@@ -409,16 +409,25 @@ export const getOptions: <
* @category getters
* @since 1.0.0
*/
export const setResponse: <Response extends ApiResponse.ApiResponse.Any>(
response: Response
export const setResponse: <
Status extends ApiResponse.ApiResponse.AnyStatus,
Body = ApiSchema.Ignored,
Headers = ApiSchema.Ignored,
R = never
>(
response: {
readonly status: Status
readonly body?: Schema.Schema<Body, any, R>
readonly headers?: Schema.Schema<Headers, any, R>
} | ApiResponse.ApiResponse<Status, Body, Headers, R>
) => <
Id extends ApiEndpoint.AnyId,
Request extends ApiRequest.ApiRequest.Any,
_ extends ApiResponse.ApiResponse.Any,
Security extends Security.Security.Any
>(
endpoint: ApiEndpoint<Id, Request, _, Security>
) => ApiEndpoint<Id, Request, Response, Security> = internal.setResponse
) => ApiEndpoint<Id, Request, ApiResponse.ApiResponse<Status, Body, Headers, R>, Security> = internal.setResponse

/**
* @category modifications
@@ -478,33 +487,26 @@ export const setResponseHeaders: <H, R2>(
* @category modifications
* @since 1.0.0
*/
export const addResponse: {
<Response2 extends ApiResponse.ApiResponse.Any>(
response: Response2
): <
Id extends ApiEndpoint.AnyId,
Request extends ApiRequest.ApiRequest.Any,
Response1 extends ApiResponse.ApiResponse.Any,
Security extends Security.Security.Any
>(
endpoint: ApiEndpoint<Id, Request, Response1, Security>
) => ApiEndpoint<Id, Request, Response1 | Response2, Security>

<Status extends ApiResponse.ApiResponse.AnyStatus, Body = ApiSchema.Ignored, Headers = ApiSchema.Ignored, R = never>(
response: {
readonly status: Status
readonly body?: Schema.Schema<Body, any, R>
readonly headers?: Schema.Schema<Headers, any, R>
}
): <
Id extends ApiEndpoint.AnyId,
Request extends ApiRequest.ApiRequest.Any,
Response1 extends ApiResponse.ApiResponse.Any,
Security extends Security.Security.Any
>(
endpoint: ApiEndpoint<Id, Request, Response1, Security>
) => ApiEndpoint<Id, Request, Response1 | ApiResponse.ApiResponse<Status, Body, Headers, R>, Security>
} = internal.addResponse
export const addResponse: <
Status extends ApiResponse.ApiResponse.AnyStatus,
Body = ApiSchema.Ignored,
Headers = ApiSchema.Ignored,
R = never
>(
response: ApiResponse.ApiResponse<Status, Body, Headers, R> | {
readonly status: Status
readonly body?: Schema.Schema<Body, any, R>
readonly headers?: Schema.Schema<Headers, any, R>
}
) => <
Id extends ApiEndpoint.AnyId,
Request extends ApiRequest.ApiRequest.Any,
Response1 extends ApiResponse.ApiResponse.Any,
Security extends Security.Security.Any
>(
endpoint: ApiEndpoint<Id, Request, Response1, Security>
) => ApiEndpoint<Id, Request, Response1 | ApiResponse.ApiResponse<Status, Body, Headers, R>, Security> =
internal.addResponse

/**
* @category modifications
4 changes: 3 additions & 1 deletion packages/effect-http/src/ApiResponse.ts
Original file line number Diff line number Diff line change
@@ -104,7 +104,9 @@ export declare namespace ApiResponse {
* @category refinements
* @since 1.0.0
*/
export const isApiResponse: (u: unknown) => u is ApiResponse.Any = internal.isApiResponse
export const isApiResponse: <S extends ApiResponse.AnyStatus = number, B = any, H = any, R = never>(
u: unknown
) => u is ApiResponse<S, B, H, R> = internal.isApiResponse

/**
* @category constructors
76 changes: 39 additions & 37 deletions packages/effect-http/src/internal/api-endpoint.ts
Original file line number Diff line number Diff line change
@@ -269,24 +269,40 @@ export const getOptions = <
) => (endpoint as ApiEndpointImpl<Id, Request, Response, Security>).options

/** @internal */
export const setResponse = <Response extends ApiResponse.ApiResponse.Any>(response: Response) =>
export const setResponse = <
Status extends ApiResponse.ApiResponse.AnyStatus,
Body = ApiSchema.Ignored,
Headers = ApiSchema.Ignored,
R = never
>(
response: {
readonly status: Status
readonly body?: Schema.Schema<Body, any, R>
readonly headers?: Schema.Schema<Headers, any, R>
} | ApiResponse.ApiResponse<Status, Body, Headers, R>
) =>
<
Id extends ApiEndpoint.ApiEndpoint.AnyId,
Request extends ApiRequest.ApiRequest.Any,
_ extends ApiResponse.ApiResponse.Any,
Security extends Security.Security.Any
>(
endpoint: ApiEndpoint.ApiEndpoint<Id, Request, _, Security>
): ApiEndpoint.ApiEndpoint<Id, Request, Response, Security> =>
new ApiEndpointImpl(
): ApiEndpoint.ApiEndpoint<Id, Request, ApiResponse.ApiResponse<Status, Body, Headers, R>, Security> => {
const newResponse = ApiResponse.isApiResponse<Status, Body, Headers, R>(response)
? response
: ApiResponse.make(response.status, response.body, response.headers)

return new ApiEndpointImpl(
getId(endpoint),
getPath(endpoint),
getMethod(endpoint),
getRequest(endpoint),
[response],
[newResponse],
getSecurity(endpoint),
getOptions(endpoint)
)
}

/** @internal */
export const setResponseStatus = <Status extends ApiResponse.ApiResponse.AnyStatus>(
@@ -365,42 +381,28 @@ export const setResponseHeaders = <H, R2>(
return setResponse(ApiResponse.setHeaders(schema)(responses[0]))(endpoint)
}

export const addResponse: {
<Response2 extends ApiResponse.ApiResponse.Any>(
response: Response2
): <
Id extends ApiEndpoint.ApiEndpoint.AnyId,
Request extends ApiRequest.ApiRequest.Any,
Response1 extends ApiResponse.ApiResponse.Any,
Security extends Security.Security.Any
>(
endpoint: ApiEndpoint.ApiEndpoint<Id, Request, Response1, Security>
) => ApiEndpoint.ApiEndpoint<Id, Request, Response1 | Response2, Security>

<Status extends ApiResponse.ApiResponse.AnyStatus, Body = ApiSchema.Ignored, Headers = ApiSchema.Ignored, R = never>(
response: {
readonly status: Status
readonly body?: Schema.Schema<Body, any, R>
readonly headers?: Schema.Schema<Headers, any, R>
}
): <
Id extends ApiEndpoint.ApiEndpoint.AnyId,
Request extends ApiRequest.ApiRequest.Any,
Response1 extends ApiResponse.ApiResponse.Any,
Security extends Security.Security.Any
>(
endpoint: ApiEndpoint.ApiEndpoint<Id, Request, Response1, Security>
) => ApiEndpoint.ApiEndpoint<Id, Request, Response1 | ApiResponse.ApiResponse<Status, Body, Headers, R>, Security>
} = (
response: ApiResponse.ApiResponse.Any | {
readonly status: number
readonly body?: Schema.Schema<Body, any, any>
readonly headers?: Schema.Schema<Headers, any, any>
export const addResponse = <
Status extends ApiResponse.ApiResponse.AnyStatus,
Body = ApiSchema.Ignored,
Headers = ApiSchema.Ignored,
R = never
>(
response: ApiResponse.ApiResponse<Status, Body, Headers, R> | {
readonly status: Status
readonly body?: Schema.Schema<Body, any, R>
readonly headers?: Schema.Schema<Headers, any, R>
}
) =>
(endpoint: ApiEndpoint.ApiEndpoint.Any) => {
<
Id extends ApiEndpoint.ApiEndpoint.AnyId,
Request extends ApiRequest.ApiRequest.Any,
Response1 extends ApiResponse.ApiResponse.Any,
Security extends Security.Security.Any
>(
endpoint: ApiEndpoint.ApiEndpoint<Id, Request, Response1, Security>
): ApiEndpoint.ApiEndpoint<Id, Request, Response1 | ApiResponse.ApiResponse<Status, Body, Headers, R>, Security> => {
const responses = getResponse(endpoint)
const newResponse = ApiResponse.isApiResponse(response)
const newResponse = ApiResponse.isApiResponse<Status, Body, Headers, R>(response)
? response
: ApiResponse.make(response.status, response.body, response.headers)

5 changes: 3 additions & 2 deletions packages/effect-http/src/internal/api-response.ts
Original file line number Diff line number Diff line change
@@ -52,8 +52,9 @@ export const defaultResponse: ApiResponse.ApiResponse.Default = new ApiResponseI
)

/** @internal */
export const isApiResponse = (u: unknown): u is ApiResponse.ApiResponse.Any =>
Predicate.hasProperty(u, TypeId) && Predicate.isObject(u[TypeId])
export const isApiResponse = <S extends ApiResponse.ApiResponse.AnyStatus = number, B = any, H = any, R = never>(
u: unknown
): u is ApiResponse.ApiResponse<S, B, H, R> => Predicate.hasProperty(u, TypeId) && Predicate.isObject(u[TypeId])

/** @internal */
export const make = <S extends ApiResponse.ApiResponse.AnyStatus, B, H, R>(
Loading

0 comments on commit c765639

Please sign in to comment.