1import * as HostProcess from "@t3tools/shared/HostProcess";
2import * as Config from "effect/Config";
3import * as Effect from "effect/Effect";
4import * as Option from "effect/Option";
5
6export type BuildArch = "arm64" | "x64" | "universal";
7export type BuildPlatform = "mac" | "linux" | "win";
8
9interface PlatformConfig {
10 readonly archChoices: ReadonlyArray<BuildArch>;
11}
12
13const WindowsProcessorArchitectureConfig = Config.all({
14 processorArchitecture: Config.String("PROCESSOR_ARCHITECTURE").pipe(Config.option),
15 processorArchitectureW6432: Config.String("PROCESSOR_ARCHITEW6432").pipe(Config.option),
16});
17
18function normalizeWindowsArch(value: string | undefined): BuildArch | undefined {
19 const normalized = value?.trim().toLowerCase();
20 if (!normalized) return undefined;
21 if (normalized.includes("arm64") || normalized === "aarch64") return "arm64";
22 if (normalized.includes("amd64") || normalized.includes("x64")) return "x64";
23 return undefined;
24}
25
26const optionToUndefined = <A>(value: Option.Option<A>): A | undefined =>
27 Option.getOrUndefined(value);
28
29const resolveHostProcessArch = Effect.fn("resolveHostProcessArch")(function* () {
30 const platform = yield* HostProcess.Platform;
31 const processArch = yield* HostProcess.Architecture;
32 if (processArch === "arm64") return "arm64";
33 if (processArch === "x64") {
34 if (platform !== "win32") return "x64";
35
36 // On Windows-on-Arm, x64 Node/Bun can run under emulation while the host
37 // still reports ARM64 via the processor environment variables.
38 const env = yield* WindowsProcessorArchitectureConfig;
39 return (
40 normalizeWindowsArch(optionToUndefined(env.processorArchitectureW6432)) ??
41 normalizeWindowsArch(optionToUndefined(env.processorArchitecture)) ??
42 "x64"
43 );
44 }
45 return undefined;
46});
47
48export const getDefaultBuildArch = Effect.fn("getDefaultBuildArch")(function* (
49 platform: BuildPlatform,
50 platformConfig: PlatformConfig,
51) {
52 const hostArch = yield* resolveHostProcessArch();
53 if (hostArch && platformConfig.archChoices.includes(hostArch)) {
54 return hostArch;
55 }
56
57 return platformConfig.archChoices[0] ?? "x64";
58});