1import * as Neon from "@/Neon";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import * as Redacted from "effect/Redacted";
5import * as FetchHttpClient from "effect/http/FetchHttpClient";
6import * as HttpClientRequest from "effect/http/HttpClientRequest";
7import * as HttpServerRequest from "effect/http/HttpServerRequest";
8import * as HttpServerResponse from "effect/http/HttpServerResponse";
9import {
10 backendAuth,
11 backendBranch,
12 backendDataApi,
13 backendGateway,
14} from "./backend-resources.ts";
15
16const bindings = Layer.mergeAll(
17 Neon.ConnectAuthHttp,
18 Neon.QueryDataApiHttp,
19 Neon.QueryAIGatewayHttp,
20).pipe(Layer.provide(FetchHttpClient.layer));
21
22export default class BackendEffect extends Neon.Function<BackendEffect>()(
23 "BackendEffect",
24 Effect.gen(function* () {
25 return { branch: yield* backendBranch, main: import.meta.url };
26 }),
27 Effect.gen(function* () {
28 const auth = yield* Neon.ConnectAuth(backendAuth);
29 const data = yield* Neon.QueryDataApi(backendDataApi);
30 const ai = yield* Neon.QueryAIGateway(backendGateway);
31 return {
32 fetch: Effect.gen(function* () {
33 const request = yield* HttpServerRequest.HttpServerRequest;
34 if (request.url === "/data-invalid-token") {
35 const response = yield* data.execute(
36 HttpClientRequest.get(""),
37 Redacted.make("invalid-end-user-token"),
38 );
39 return HttpServerResponse.text(String(response.status));
40 }
41 if (request.url === "/data-foreign-origin") {
42 const rejected = yield* data
43 .execute(
44 HttpClientRequest.get("https://example.com/"),
45 Redacted.make("invalid-end-user-token"),
46 )
47 .pipe(
48 Effect.as(false),
49 Effect.catchTag("DataApiRequestError", () =>
50 Effect.succeed(true),
51 ),
52 );
53 return yield* HttpServerResponse.json({ rejected });
54 }
55 return yield* HttpServerResponse.json({
56 authUrl: yield* auth.baseUrl,
57 jwksUrl: yield* auth.jwksUrl,
58 dataUrl: yield* data.baseUrl,
59 aiUrl: yield* ai.baseUrl,
60 chatUrl: yield* ai.chatBaseUrl,
61 responsesUrl: yield* ai.responsesBaseUrl,
62 hasToken: Redacted.value(yield* ai.token).length > 0,
63 });
64 }).pipe(Effect.orDie),
65 };
66 }).pipe(Effect.provide(bindings)),
67) {}