1import * as Fly from "alchemy/Fly";
2import * as Config from "effect/Config";
3import * as Effect from "effect/Effect";
4import * as FileSystem from "effect/FileSystem";
5import * as Redacted from "effect/Redacted";
6import { HttpServerRequest } from "effect/http/HttpServerRequest";
7import * as HttpServerResponse from "effect/http/HttpServerResponse";
8
9/**
10 * HTTP Sprite. Yield FileSystem in init, not inside fetch.
11 * Config.Redacted is written onto the Sprite at deploy time.
12 */
13export default class Box extends Fly.Sprite<Box>()(
14 "Box",
15 {
16 main: import.meta.url,
17 urlAuth: "public",
18 port: 3000,
19 },
20 Effect.gen(function* () {
21 const marker = yield* Config.String("SPRITE_MARKER").pipe(
22 Config.withDefault("hello-from-fly-sprite"),
23 );
24 const apiKey = yield* Config.Redacted("API_KEY").pipe(
25 Config.withDefault(Redacted.make("unused")),
26 );
27 const fs = yield* FileSystem.FileSystem;
28 yield* fs.makeDirectory("/tmp", { recursive: true }).pipe(Effect.orDie);
29 yield* fs.writeFileString("/tmp/marker.txt", marker).pipe(Effect.orDie);
30
31 return {
32 fetch: Effect.gen(function* () {
33 const request = yield* HttpServerRequest;
34 const url = new URL(request.url, "http://sprite");
35 if (url.pathname === "/health") {
36 return yield* HttpServerResponse.json({ ok: true });
37 }
38 void Redacted.value(apiKey);
39 return yield* HttpServerResponse.json({
40 ok: true,
41 marker,
42 });
43 }),
44 };
45 }),
46) {}