import * as Clock from "effect/Clock";import type { RelayClientInstallProgressEvent, RelayClientInstallProgressStage,} from "@t3tools/contracts";import * as Config from "effect/Config";import * as Context from "effect/Context";import * as Crypto from "effect/Crypto";import * as Effect from "effect/Effect";import * as Encoding from "effect/Encoding";import * as FileSystem from "effect/FileSystem";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as Path from "effect/Path";import * as PlatformError from "effect/PlatformError";import * as Schema from "effect/Schema";import * as Semaphore from "effect/Semaphore";import * as HttpClient from "effect/unstable/http/HttpClient";import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";import * as ChildProcess from "effect/unstable/process/ChildProcess";import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; import { HostProcessArchitecture, HostProcessPlatform } from "./hostProcess.ts";import { getUrlDiagnostics } from "./urlDiagnostics.ts"; export const CLOUDFLARED_VERSION = "2026.5.2";export const CLOUDFLARED_PATH_ENV_NAME = "T3CODE_CLOUDFLARED_PATH"; export type RelayClientExecutableSource = "override" | "managed" | "path"; export type RelayClientStatus = | { readonly status: "available"; readonly executablePath: string; readonly source: RelayClientExecutableSource; readonly version: string; } | { readonly status: "missing"; readonly version: string; } | { readonly status: "unsupported"; readonly platform: NodeJS.Platform; readonly arch: string; readonly version: string; }; export type AvailableRelayClient = Extract<RelayClientStatus, { readonly status: "available" }>; const RelayClientUrlDiagnosticFields = { urlInputLength: Schema.Number, urlProtocol: Schema.optional(Schema.String), urlHostname: Schema.optional(Schema.String),}; function relayClientUrlDiagnostics(input: string) { const diagnostics = getUrlDiagnostics(input); return { urlInputLength: diagnostics.inputLength, ...(diagnostics.protocol === undefined ? {} : { urlProtocol: diagnostics.protocol }), ...(diagnostics.hostname === undefined ? {} : { urlHostname: diagnostics.hostname }), };} export class RelayClientDownloadError extends Schema.TaggedErrorClass<RelayClientDownloadError>()( "RelayClientDownloadError", { ...RelayClientUrlDiagnosticFields, cause: Schema.Defect(), },) { override get message(): string { return "Could not download the relay client."; }} export class RelayClientDownloadReadError extends Schema.TaggedErrorClass<RelayClientDownloadReadError>()( "RelayClientDownloadReadError", { ...RelayClientUrlDiagnosticFields, cause: Schema.Defect(), },) { override get message(): string { return "Could not read the downloaded relay client binary."; }} export class RelayClientChecksumMismatchError extends Schema.TaggedErrorClass<RelayClientChecksumMismatchError>()( "RelayClientChecksumMismatchError", { expectedChecksum: Schema.String, actualChecksum: Schema.String, },) { override get message(): string { return "Downloaded relay client checksum did not match the pinned release."; }} export class RelayClientInstallLockedError extends Schema.TaggedErrorClass<RelayClientInstallLockedError>()( "RelayClientInstallLockedError", { lockPath: Schema.String, },) { override get message(): string { return "Another relay client installation is still in progress."; }} export class RelayClientOverrideMissingError extends Schema.TaggedErrorClass<RelayClientOverrideMissingError>()( "RelayClientOverrideMissingError", { executablePath: Schema.String, },) { override get message(): string { return `${CLOUDFLARED_PATH_ENV_NAME} does not point to an executable file.`; }} export class RelayClientUnsupportedPlatformError extends Schema.TaggedErrorClass<RelayClientUnsupportedPlatformError>()( "RelayClientUnsupportedPlatformError", { platform: Schema.String, arch: Schema.String, },) { override get message(): string { return `T3 Code does not provide a managed relay client binary for ${this.platform}-${this.arch}.`; }} export class RelayClientChecksumVerificationError extends Schema.TaggedErrorClass<RelayClientChecksumVerificationError>()( "RelayClientChecksumVerificationError", { ...RelayClientUrlDiagnosticFields, expectedChecksum: Schema.String, cause: Schema.Defect(), },) { override get message(): string { return "Could not verify the downloaded relay client checksum."; }} export class RelayClientExecutableValidationError extends Schema.TaggedErrorClass<RelayClientExecutableValidationError>()( "RelayClientExecutableValidationError", { executablePath: Schema.String, cause: Schema.Defect(), },) { override get message(): string { return "The downloaded relay client binary did not run."; }} export class RelayClientDirectoryCreateError extends Schema.TaggedErrorClass<RelayClientDirectoryCreateError>()( "RelayClientDirectoryCreateError", { directoryPath: Schema.String, cause: Schema.Defect(), },) { override get message(): string { return "Could not create the relay client tool directory."; }} export class RelayClientInstallLockAcquireError extends Schema.TaggedErrorClass<RelayClientInstallLockAcquireError>()( "RelayClientInstallLockAcquireError", { lockPath: Schema.String, cause: Schema.Defect(), },) { override get message(): string { return "Could not acquire the relay client installation lock."; }} export class RelayClientDownloadWriteError extends Schema.TaggedErrorClass<RelayClientDownloadWriteError>()( "RelayClientDownloadWriteError", { archivePath: Schema.String, cause: Schema.Defect(), },) { override get message(): string { return "Could not write the relay client download."; }} export class RelayClientArchiveExtractError extends Schema.TaggedErrorClass<RelayClientArchiveExtractError>()( "RelayClientArchiveExtractError", { archivePath: Schema.String, destinationDirectory: Schema.String, cause: Schema.Defect(), },) { override get message(): string { return "Could not extract the relay client."; }} export class RelayClientExecutablePermissionError extends Schema.TaggedErrorClass<RelayClientExecutablePermissionError>()( "RelayClientExecutablePermissionError", { executablePath: Schema.String, cause: Schema.Defect(), },) { override get message(): string { return "Could not make the relay client executable."; }} export class RelayClientStageError extends Schema.TaggedErrorClass<RelayClientStageError>()( "RelayClientStageError", { sourcePath: Schema.String, destinationPath: Schema.String, cause: Schema.Defect(), },) { override get message(): string { return "Could not stage the relay client."; }} export class RelayClientActivationError extends Schema.TaggedErrorClass<RelayClientActivationError>()( "RelayClientActivationError", { sourcePath: Schema.String, destinationPath: Schema.String, cause: Schema.Defect(), },) { override get message(): string { return "Could not activate the relay client."; }} export class RelayClientInstallWriteError extends Schema.TaggedErrorClass<RelayClientInstallWriteError>()( "RelayClientInstallWriteError", { managedPath: Schema.String, cause: Schema.Defect(), },) { override get message(): string { return "Could not install the relay client."; }} export const RelayClientInstallError = Schema.Union([ RelayClientDownloadError, RelayClientDownloadReadError, RelayClientChecksumMismatchError, RelayClientInstallLockedError, RelayClientOverrideMissingError, RelayClientUnsupportedPlatformError, RelayClientChecksumVerificationError, RelayClientExecutableValidationError, RelayClientDirectoryCreateError, RelayClientInstallLockAcquireError, RelayClientDownloadWriteError, RelayClientArchiveExtractError, RelayClientExecutablePermissionError, RelayClientStageError, RelayClientActivationError, RelayClientInstallWriteError,]);export type RelayClientInstallError = typeof RelayClientInstallError.Type; class CloudflaredCommandError extends Schema.TaggedErrorClass<CloudflaredCommandError>()( "CloudflaredCommandError", { command: Schema.String, exitCode: Schema.Number, },) { override get message(): string { return `${this.command} exited with code ${this.exitCode}.`; }} export const isRelayClientInstallError = Schema.is(RelayClientInstallError); export interface CloudflaredReleaseAsset { readonly url: string; readonly sha256: string; readonly archive: "binary" | "tgz";} const CLOUDFLARED_RELEASE_ASSETS: Readonly< Partial<Record<`${NodeJS.Platform}-${string}`, CloudflaredReleaseAsset>>> = { "darwin-arm64": { url: "https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-darwin-arm64.tgz", sha256: "ba94054c9fd4297645093d59d51442e5e546d07bb0516120e694a13d5b216d38", archive: "tgz", }, "darwin-x64": { url: "https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-darwin-amd64.tgz", sha256: "7240f709506bc2c1eb9da4d89cf2555499c60280ecb854b7d80e8f17d4b7903d", archive: "tgz", }, "linux-arm64": { url: "https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-linux-arm64", sha256: "5a4e8ce2701105271412059f44b6a0bf1ae4542b4d98ff3180c0c019443a5815", archive: "binary", }, "linux-x64": { url: "https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-linux-amd64", sha256: "5286698547f03df745adb2355f04c12dde52ef425491e81f433642d695521886", archive: "binary", }, "win32-x64": { url: "https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-windows-amd64.exe", sha256: "20b9638f685333d623798e733effbad2487093f15ba592f6c7752360ff3b7ab7", archive: "binary", },}; const INSTALL_LOCK_RETRY_COUNT = 100;const INSTALL_LOCK_RETRY_DELAY = "100 millis";const INSTALL_LOCK_STALE_MS = 5 * 60 * 1_000; const trimmedString = (name: string) => Config.string(name).pipe( Config.option, Config.map( Option.flatMap((value) => { const trimmed = value.trim(); return trimmed.length > 0 ? Option.some(trimmed) : Option.none(); }), ), ); const CloudflaredConfig = Config.all({ executableOverride: trimmedString(CLOUDFLARED_PATH_ENV_NAME), path: trimmedString("PATH"),}); export interface CloudflaredRelayClientOptions { readonly baseDir: string; readonly releaseAsset?: CloudflaredReleaseAsset;} export class RelayClient extends Context.Service< RelayClient, { readonly resolve: Effect.Effect<RelayClientStatus>; readonly install: Effect.Effect<AvailableRelayClient, RelayClientInstallError>; readonly installWithProgress: ( report: (event: RelayClientInstallProgressEvent) => Effect.Effect<void>, ) => Effect.Effect<AvailableRelayClient, RelayClientInstallError>; }>()("@t3tools/shared/relayClient") {} function executableFileName(platform: NodeJS.Platform): string { return platform === "win32" ? "cloudflared.exe" : "cloudflared";} function resolveReleaseAsset( platform: NodeJS.Platform, arch: string,): CloudflaredReleaseAsset | null { return CLOUDFLARED_RELEASE_ASSETS[`${platform}-${arch}`] ?? null;} function isAlreadyExists(error: PlatformError.PlatformError): boolean { return error.reason._tag === "AlreadyExists";} export const makeCloudflaredRelayClient = Effect.fn("cloudflared.make")(function* ( options: CloudflaredRelayClientOptions,): Effect.fn.Return< RelayClient["Service"], never, | ChildProcessSpawner.ChildProcessSpawner | Crypto.Crypto | FileSystem.FileSystem | HttpClient.HttpClient | Path.Path> { const crypto = yield* Crypto.Crypto; const fileSystem = yield* FileSystem.FileSystem; const httpClient = yield* HttpClient.HttpClient; const path = yield* Path.Path; const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; const installSemaphore = yield* Semaphore.make(1); const platform = yield* HostProcessPlatform; const arch = yield* HostProcessArchitecture; const releaseAsset = options.releaseAsset ?? resolveReleaseAsset(platform, arch); const loadCloudflaredConfig = Effect.suspend(() => CloudflaredConfig).pipe(Effect.orDie); const managedPath = path.join( options.baseDir, "tools", "cloudflared", CLOUDFLARED_VERSION, `${platform}-${arch}`, executableFileName(platform), ); const isExecutableFile = Effect.fn("cloudflared.isExecutableFile")(function* ( executablePath: string, ) { const info = yield* fileSystem.stat(executablePath).pipe(Effect.option); if (Option.isNone(info) || info.value.type !== "File") return false; return platform === "win32" || (info.value.mode & 0o111) !== 0; }); const resolvePathExecutable = Effect.gen(function* () { const config = yield* loadCloudflaredConfig; const pathValue = Option.getOrUndefined(config.path); if (!pathValue) return null; const delimiter = platform === "win32" ? ";" : ":"; for (const directory of pathValue.split(delimiter)) { const trimmed = directory.trim().replace(/^"|"$/gu, ""); if (trimmed.length === 0) continue; const candidate = path.join(trimmed, executableFileName(platform)); if (yield* isExecutableFile(candidate)) return candidate; } return null; }); const resolve: RelayClient["Service"]["resolve"] = Effect.gen(function* () { const config = yield* loadCloudflaredConfig; if (Option.isSome(config.executableOverride)) { return (yield* isExecutableFile(config.executableOverride.value)) ? { status: "available", executablePath: config.executableOverride.value, source: "override", version: CLOUDFLARED_VERSION, } : { status: "missing", version: CLOUDFLARED_VERSION }; } if (yield* isExecutableFile(managedPath)) { return { status: "available", executablePath: managedPath, source: "managed", version: CLOUDFLARED_VERSION, }; } const pathExecutable = yield* resolvePathExecutable; if (pathExecutable) { return { status: "available", executablePath: pathExecutable, source: "path", version: CLOUDFLARED_VERSION, }; } return releaseAsset ? { status: "missing", version: CLOUDFLARED_VERSION } : { status: "unsupported", platform, arch, version: CLOUDFLARED_VERSION, }; }); const runCommand = Effect.fn("cloudflared.runCommand")(function* ( command: string, args: ReadonlyArray<string>, ) { const child = yield* spawner.spawn( ChildProcess.make(command, args, { shell: false, stdout: "ignore", stderr: "ignore", }), ); const exitCode = Number(yield* child.exitCode); if (exitCode !== 0) { return yield* new CloudflaredCommandError({ command, exitCode }); } }); const downloadAsset = Effect.fn("cloudflared.downloadAsset")(function* ( asset: CloudflaredReleaseAsset, report: (stage: RelayClientInstallProgressStage) => Effect.Effect<void>, ) { yield* report("downloading"); const response = yield* httpClient.execute(HttpClientRequest.get(asset.url)).pipe( Effect.flatMap(HttpClientResponse.filterStatusOk), Effect.mapError( (cause) => new RelayClientDownloadError({ ...relayClientUrlDiagnostics(asset.url),Lines 1–500 of 724. Load more
import * as Clock from "effect/Clock"; import type { RelayClientInstallProgressEvent, RelayClientInstallProgressStage, } from "@t3tools/contracts"; import * as Config from "effect/Config"; import * as Context from "effect/Context"; import * as Crypto from "effect/Crypto"; import * as Effect from "effect/Effect"; import * as Encoding from "effect/Encoding"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as Path from "effect/Path"; import * as PlatformError from "effect/PlatformError"; import * as Schema from "effect/Schema"; import * as Semaphore from "effect/Semaphore"; import * as HttpClient from "effect/unstable/http/HttpClient"; import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"; import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"; import * as ChildProcess from "effect/unstable/process/ChildProcess"; import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; import { HostProcessArchitecture, HostProcessPlatform } from "./hostProcess.ts"; import { getUrlDiagnostics } from "./urlDiagnostics.ts"; export const CLOUDFLARED_VERSION = "2026.5.2"; export const CLOUDFLARED_PATH_ENV_NAME = "T3CODE_CLOUDFLARED_PATH"; export type RelayClientExecutableSource = "override" | "managed" | "path"; export type RelayClientStatus = | { readonly status: "available"; readonly executablePath: string; readonly source: RelayClientExecutableSource; readonly version: string; } | { readonly status: "missing"; readonly version: string; } | { readonly status: "unsupported"; readonly platform: NodeJS.Platform; readonly arch: string; readonly version: string; }; export type AvailableRelayClient = Extract<RelayClientStatus, { readonly status: "available" }>; const RelayClientUrlDiagnosticFields = { urlInputLength: Schema.Number, urlProtocol: Schema.optional(Schema.String), urlHostname: Schema.optional(Schema.String), }; function relayClientUrlDiagnostics(input: string) { const diagnostics = getUrlDiagnostics(input); return { urlInputLength: diagnostics.inputLength, ...(diagnostics.protocol === undefined ? {} : { urlProtocol: diagnostics.protocol }), ...(diagnostics.hostname === undefined ? {} : { urlHostname: diagnostics.hostname }), }; } export class RelayClientDownloadError extends Schema.TaggedErrorClass<RelayClientDownloadError>()( "RelayClientDownloadError", { ...RelayClientUrlDiagnosticFields, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not download the relay client."; } } export class RelayClientDownloadReadError extends Schema.TaggedErrorClass<RelayClientDownloadReadError>()( "RelayClientDownloadReadError", { ...RelayClientUrlDiagnosticFields, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not read the downloaded relay client binary."; } } export class RelayClientChecksumMismatchError extends Schema.TaggedErrorClass<RelayClientChecksumMismatchError>()( "RelayClientChecksumMismatchError", { expectedChecksum: Schema.String, actualChecksum: Schema.String, }, ) { override get message(): string { return "Downloaded relay client checksum did not match the pinned release."; } } export class RelayClientInstallLockedError extends Schema.TaggedErrorClass<RelayClientInstallLockedError>()( "RelayClientInstallLockedError", { lockPath: Schema.String, }, ) { override get message(): string { return "Another relay client installation is still in progress."; } } export class RelayClientOverrideMissingError extends Schema.TaggedErrorClass<RelayClientOverrideMissingError>()( "RelayClientOverrideMissingError", { executablePath: Schema.String, }, ) { override get message(): string { return `${CLOUDFLARED_PATH_ENV_NAME} does not point to an executable file.`; } } export class RelayClientUnsupportedPlatformError extends Schema.TaggedErrorClass<RelayClientUnsupportedPlatformError>()( "RelayClientUnsupportedPlatformError", { platform: Schema.String, arch: Schema.String, }, ) { override get message(): string { return `T3 Code does not provide a managed relay client binary for ${this.platform}-${this.arch}.`; } } export class RelayClientChecksumVerificationError extends Schema.TaggedErrorClass<RelayClientChecksumVerificationError>()( "RelayClientChecksumVerificationError", { ...RelayClientUrlDiagnosticFields, expectedChecksum: Schema.String, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not verify the downloaded relay client checksum."; } } export class RelayClientExecutableValidationError extends Schema.TaggedErrorClass<RelayClientExecutableValidationError>()( "RelayClientExecutableValidationError", { executablePath: Schema.String, cause: Schema.Defect(), }, ) { override get message(): string { return "The downloaded relay client binary did not run."; } } export class RelayClientDirectoryCreateError extends Schema.TaggedErrorClass<RelayClientDirectoryCreateError>()( "RelayClientDirectoryCreateError", { directoryPath: Schema.String, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not create the relay client tool directory."; } } export class RelayClientInstallLockAcquireError extends Schema.TaggedErrorClass<RelayClientInstallLockAcquireError>()( "RelayClientInstallLockAcquireError", { lockPath: Schema.String, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not acquire the relay client installation lock."; } } export class RelayClientDownloadWriteError extends Schema.TaggedErrorClass<RelayClientDownloadWriteError>()( "RelayClientDownloadWriteError", { archivePath: Schema.String, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not write the relay client download."; } } export class RelayClientArchiveExtractError extends Schema.TaggedErrorClass<RelayClientArchiveExtractError>()( "RelayClientArchiveExtractError", { archivePath: Schema.String, destinationDirectory: Schema.String, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not extract the relay client."; } } export class RelayClientExecutablePermissionError extends Schema.TaggedErrorClass<RelayClientExecutablePermissionError>()( "RelayClientExecutablePermissionError", { executablePath: Schema.String, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not make the relay client executable."; } } export class RelayClientStageError extends Schema.TaggedErrorClass<RelayClientStageError>()( "RelayClientStageError", { sourcePath: Schema.String, destinationPath: Schema.String, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not stage the relay client."; } } export class RelayClientActivationError extends Schema.TaggedErrorClass<RelayClientActivationError>()( "RelayClientActivationError", { sourcePath: Schema.String, destinationPath: Schema.String, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not activate the relay client."; } } export class RelayClientInstallWriteError extends Schema.TaggedErrorClass<RelayClientInstallWriteError>()( "RelayClientInstallWriteError", { managedPath: Schema.String, cause: Schema.Defect(), }, ) { override get message(): string { return "Could not install the relay client."; } } export const RelayClientInstallError = Schema.Union([ RelayClientDownloadError, RelayClientDownloadReadError, RelayClientChecksumMismatchError, RelayClientInstallLockedError, RelayClientOverrideMissingError, RelayClientUnsupportedPlatformError, RelayClientChecksumVerificationError, RelayClientExecutableValidationError, RelayClientDirectoryCreateError, RelayClientInstallLockAcquireError, RelayClientDownloadWriteError, RelayClientArchiveExtractError, RelayClientExecutablePermissionError, RelayClientStageError, RelayClientActivationError, RelayClientInstallWriteError, ]); export type RelayClientInstallError = typeof RelayClientInstallError.Type; class CloudflaredCommandError extends Schema.TaggedErrorClass<CloudflaredCommandError>()( "CloudflaredCommandError", { command: Schema.String, exitCode: Schema.Number, }, ) { override get message(): string { return `${this.command} exited with code ${this.exitCode}.`; } } export const isRelayClientInstallError = Schema.is(RelayClientInstallError); export interface CloudflaredReleaseAsset { readonly url: string; readonly sha256: string; readonly archive: "binary" | "tgz"; } const CLOUDFLARED_RELEASE_ASSETS: Readonly< Partial<Record<`${NodeJS.Platform}-${string}`, CloudflaredReleaseAsset>> > = { "darwin-arm64": { url: "https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-darwin-arm64.tgz", sha256: "ba94054c9fd4297645093d59d51442e5e546d07bb0516120e694a13d5b216d38", archive: "tgz", }, "darwin-x64": { url: "https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-darwin-amd64.tgz", sha256: "7240f709506bc2c1eb9da4d89cf2555499c60280ecb854b7d80e8f17d4b7903d", archive: "tgz", }, "linux-arm64": { url: "https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-linux-arm64", sha256: "5a4e8ce2701105271412059f44b6a0bf1ae4542b4d98ff3180c0c019443a5815", archive: "binary", }, "linux-x64": { url: "https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-linux-amd64", sha256: "5286698547f03df745adb2355f04c12dde52ef425491e81f433642d695521886", archive: "binary", }, "win32-x64": { url: "https://github.com/cloudflare/cloudflared/releases/download/2026.5.2/cloudflared-windows-amd64.exe", sha256: "20b9638f685333d623798e733effbad2487093f15ba592f6c7752360ff3b7ab7", archive: "binary", }, }; const INSTALL_LOCK_RETRY_COUNT = 100; const INSTALL_LOCK_RETRY_DELAY = "100 millis"; const INSTALL_LOCK_STALE_MS = 5 * 60 * 1_000; const trimmedString = (name: string) => Config.string(name).pipe( Config.option, Config.map( Option.flatMap((value) => { const trimmed = value.trim(); return trimmed.length > 0 ? Option.some(trimmed) : Option.none(); }), ), ); const CloudflaredConfig = Config.all({ executableOverride: trimmedString(CLOUDFLARED_PATH_ENV_NAME), path: trimmedString("PATH"), }); export interface CloudflaredRelayClientOptions { readonly baseDir: string; readonly releaseAsset?: CloudflaredReleaseAsset; } export class RelayClient extends Context.Service< RelayClient, { readonly resolve: Effect.Effect<RelayClientStatus>; readonly install: Effect.Effect<AvailableRelayClient, RelayClientInstallError>; readonly installWithProgress: ( report: (event: RelayClientInstallProgressEvent) => Effect.Effect<void>, ) => Effect.Effect<AvailableRelayClient, RelayClientInstallError>; } >()("@t3tools/shared/relayClient") {} function executableFileName(platform: NodeJS.Platform): string { return platform === "win32" ? "cloudflared.exe" : "cloudflared"; } function resolveReleaseAsset( platform: NodeJS.Platform, arch: string, ): CloudflaredReleaseAsset | null { return CLOUDFLARED_RELEASE_ASSETS[`${platform}-${arch}`] ?? null; } function isAlreadyExists(error: PlatformError.PlatformError): boolean { return error.reason._tag === "AlreadyExists"; } export const makeCloudflaredRelayClient = Effect.fn("cloudflared.make")(function* ( options: CloudflaredRelayClientOptions, ): Effect.fn.Return< RelayClient["Service"], never, | ChildProcessSpawner.ChildProcessSpawner | Crypto.Crypto | FileSystem.FileSystem | HttpClient.HttpClient | Path.Path > { const crypto = yield* Crypto.Crypto; const fileSystem = yield* FileSystem.FileSystem; const httpClient = yield* HttpClient.HttpClient; const path = yield* Path.Path; const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; const installSemaphore = yield* Semaphore.make(1); const platform = yield* HostProcessPlatform; const arch = yield* HostProcessArchitecture; const releaseAsset = options.releaseAsset ?? resolveReleaseAsset(platform, arch); const loadCloudflaredConfig = Effect.suspend(() => CloudflaredConfig).pipe(Effect.orDie); const managedPath = path.join( options.baseDir, "tools", "cloudflared", CLOUDFLARED_VERSION, `${platform}-${arch}`, executableFileName(platform), ); const isExecutableFile = Effect.fn("cloudflared.isExecutableFile")(function* ( executablePath: string, ) { const info = yield* fileSystem.stat(executablePath).pipe(Effect.option); if (Option.isNone(info) || info.value.type !== "File") return false; return platform === "win32" || (info.value.mode & 0o111) !== 0; }); const resolvePathExecutable = Effect.gen(function* () { const config = yield* loadCloudflaredConfig; const pathValue = Option.getOrUndefined(config.path); if (!pathValue) return null; const delimiter = platform === "win32" ? ";" : ":"; for (const directory of pathValue.split(delimiter)) { const trimmed = directory.trim().replace(/^"|"$/gu, ""); if (trimmed.length === 0) continue; const candidate = path.join(trimmed, executableFileName(platform)); if (yield* isExecutableFile(candidate)) return candidate; } return null; }); const resolve: RelayClient["Service"]["resolve"] = Effect.gen(function* () { const config = yield* loadCloudflaredConfig; if (Option.isSome(config.executableOverride)) { return (yield* isExecutableFile(config.executableOverride.value)) ? { status: "available", executablePath: config.executableOverride.value, source: "override", version: CLOUDFLARED_VERSION, } : { status: "missing", version: CLOUDFLARED_VERSION }; } if (yield* isExecutableFile(managedPath)) { return { status: "available", executablePath: managedPath, source: "managed", version: CLOUDFLARED_VERSION, }; } const pathExecutable = yield* resolvePathExecutable; if (pathExecutable) { return { status: "available", executablePath: pathExecutable, source: "path", version: CLOUDFLARED_VERSION, }; } return releaseAsset ? { status: "missing", version: CLOUDFLARED_VERSION } : { status: "unsupported", platform, arch, version: CLOUDFLARED_VERSION, }; }); const runCommand = Effect.fn("cloudflared.runCommand")(function* ( command: string, args: ReadonlyArray<string>, ) { const child = yield* spawner.spawn( ChildProcess.make(command, args, { shell: false, stdout: "ignore", stderr: "ignore", }), ); const exitCode = Number(yield* child.exitCode); if (exitCode !== 0) { return yield* new CloudflaredCommandError({ command, exitCode }); } }); const downloadAsset = Effect.fn("cloudflared.downloadAsset")(function* ( asset: CloudflaredReleaseAsset, report: (stage: RelayClientInstallProgressStage) => Effect.Effect<void>, ) { yield* report("downloading"); const response = yield* httpClient.execute(HttpClientRequest.get(asset.url)).pipe( Effect.flatMap(HttpClientResponse.filterStatusOk), Effect.mapError( (cause) => new RelayClientDownloadError({ ...relayClientUrlDiagnostics(asset.url),