Implementing Vite Dev Server Middleware in an Effect Http App
Since I haven't found any example on how to use an express (connect) middleware (vite dev server for example) inside an Effect Http app, I have decided to create my own. It's a bit dirty but it works and since the middleware is only really applied in dev mode, any side effects are kept local.
class MiddlewareError extends Data.TaggedError("MiddlewareError")<{
message: string;
}> {}
const viteMiddleware = HttpMiddleware.make((app) =>
Effect.gen(function* () {
if (!viteDevServer) return yield* app;
const request = yield* HttpServerRequest.HttpServerRequest;
const req = NodeHttpServerRequest.toIncomingMessage(request);
const res = NodeHttpServerRequest.toServerResponse(request);
return yield* Effect.async<
Effect.Effect.Success<typeof app>,
Effect.Effect.Error<typeof app> | MiddlewareError,
Effect.Effect.Context<typeof app>
>((resume) => {
const listener = () => {
resume(
Effect.succeed(
HttpServerResponse.raw(null, {
status: res.statusCode,
statusText: res.statusMessage,
}),
),
);
};
res.once("finish", listener);
const next = (err?: any) => {
if (err) {
return resume(
Effect.fail(new MiddlewareError({ message: String(err) })),
);
}
res.off("finish", listener);
return resume(app);
};
viteDevServer.middlewares(req, res, next);
});
}),
);class MiddlewareError extends Data.TaggedError("MiddlewareError")<{
message: string;
}> {}
const viteMiddleware = HttpMiddleware.make((app) =>
Effect.gen(function* () {
if (!viteDevServer) return yield* app;
const request = yield* HttpServerRequest.HttpServerRequest;
const req = NodeHttpServerRequest.toIncomingMessage(request);
const res = NodeHttpServerRequest.toServerResponse(request);
return yield* Effect.async<
Effect.Effect.Success<typeof app>,
Effect.Effect.Error<typeof app> | MiddlewareError,
Effect.Effect.Context<typeof app>
>((resume) => {
const listener = () => {
resume(
Effect.succeed(
HttpServerResponse.raw(null, {
status: res.statusCode,
statusText: res.statusMessage,
}),
),
);
};
res.once("finish", listener);
const next = (err?: any) => {
if (err) {
return resume(
Effect.fail(new MiddlewareError({ message: String(err) })),
);
}
res.off("finish", listener);
return resume(app);
};
viteDevServer.middlewares(req, res, next);
});
}),
);