t3-code-android-nightly/scripts/mock-update-server.ts
Julius Marminge 194c73f3f9
chore(deps): upgrade Effect to stable 4.0.1 (#16138)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 13:15:14 -07:00

158 lines
5 KiB
TypeScript

// @effect-diagnostics-next-line nodeBuiltinImport:off - NodeHttpServer.layer takes `NodeHttp.createServer` as arg
import * as NodeHttp from "node:http";
import { NodeHttpServer, NodeRuntime, NodeServices } from "@effect/platform-node";
import * as Config from "effect/Config";
import * as Effect from "effect/Effect";
import * as FileSystem from "effect/FileSystem";
import * as Layer from "effect/Layer";
import * as Path from "effect/Path";
import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/http";
interface MockUpdateServerConfig {
readonly port: number;
readonly rootRealPath: string;
}
const resolveMockUpdateServerConfig = Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const config = yield* Config.all({
port: Config.Port("T3CODE_DESKTOP_MOCK_UPDATE_SERVER_PORT").pipe(Config.withDefault(3000)),
root: Config.String("T3CODE_DESKTOP_MOCK_UPDATE_SERVER_ROOT").pipe(
Config.withDefault("../release-mock"),
),
});
const resolvedRoot = path.resolve(import.meta.dirname, config.root);
return {
port: config.port,
rootRealPath: yield* fileSystem.realPath(resolvedRoot),
} satisfies MockUpdateServerConfig;
});
const isOutsideRoot = (rootRealPath: string, filePath: string) =>
Effect.gen(function* () {
const path = yield* Path.Path;
const relativePath = path.relative(rootRealPath, filePath);
return (
relativePath === ".." || relativePath.startsWith("../") || relativePath.startsWith("..\\")
);
});
const isWithinRoot = (rootRealPath: string, filePath: string) =>
Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
const resolvedFilePath = yield* fileSystem.realPath(filePath).pipe(
Effect.match({
onFailure: () => undefined,
onSuccess: (resolvedPath) => resolvedPath,
}),
);
return (
resolvedFilePath !== undefined && !(yield* isOutsideRoot(rootRealPath, resolvedFilePath))
);
});
const resolveRequestedFilePath = (rootRealPath: string, requestUrl: string | undefined) =>
Effect.gen(function* () {
const path = yield* Path.Path;
const rawPath = (requestUrl ?? "/").split("?", 1)[0] ?? "/";
const decodedPath = yield* Effect.try({
try: () => decodeURIComponent(rawPath),
catch: () => null,
}).pipe(
Effect.match({
onFailure: () => undefined,
onSuccess: (value) => value,
}),
);
if (!decodedPath) {
return undefined;
}
if (decodedPath.includes("\0")) {
return undefined;
}
const filePath = path.resolve(
rootRealPath,
`.${decodedPath.startsWith("/") ? decodedPath : `/${decodedPath}`}`,
);
return (yield* isOutsideRoot(rootRealPath, filePath)) ? undefined : filePath;
});
const isServableFile = (rootRealPath: string, filePath: string) =>
Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
const stat = yield* fileSystem.stat(filePath).pipe(
Effect.match({
onFailure: () => undefined,
onSuccess: (info) => info,
}),
);
if (stat?.type !== "File") {
return false;
}
return yield* isWithinRoot(rootRealPath, filePath);
});
export const makeMockUpdateRouteLayer = (rootRealPath: string) => {
return HttpRouter.add(
"*",
"*",
Effect.gen(function* () {
const request = yield* HttpServerRequest.HttpServerRequest;
const requestPath = (request.url ?? "/").split("?", 1)[0] ?? "/";
yield* Effect.logInfo(`Request received for path: ${requestPath}`);
const filePath = yield* resolveRequestedFilePath(rootRealPath, request.url);
if (!filePath) {
yield* Effect.logWarning(`Attempted to access file outside of root: ${request.url ?? "/"}`);
return HttpServerResponse.text("Not Found", { status: 404 });
}
if (!(yield* isServableFile(rootRealPath, filePath))) {
yield* Effect.logWarning(`Attempted to access invalid file: ${filePath}`);
return HttpServerResponse.text("Not Found", { status: 404 });
}
yield* Effect.logInfo(`Serving file: ${filePath}`);
return yield* HttpServerResponse.file(filePath, { status: 200 });
}).pipe(
Effect.catchCause((cause) =>
Effect.gen(function* () {
yield* Effect.logError(`Unhandled mock update request failure: ${cause}`);
return HttpServerResponse.text("Internal Server Error", { status: 500 });
}),
),
),
);
};
const makeMockUpdateServerLayer = (config: MockUpdateServerConfig) =>
HttpRouter.serve(makeMockUpdateRouteLayer(config.rootRealPath)).pipe(
Layer.provideMerge(
NodeHttpServer.layer(NodeHttp.createServer, {
host: "localhost",
port: config.port,
}),
),
Layer.provideMerge(NodeServices.layer),
);
if (import.meta.main) {
resolveMockUpdateServerConfig.pipe(
Effect.map(makeMockUpdateServerLayer),
Layer.unwrap,
Layer.launch,
Effect.provide(NodeServices.layer),
NodeRuntime.runMain,
);
}