Last active
August 25, 2025 13:20
-
-
Save RareScrap/0ba9e5aba0f996a31538f2b7869d57ac to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import os from 'node:os'; | |
| export function getOsPlatformUsingPlatform(): NodeJS.Platform | undefined { | |
| const sanitizedOsType = os.type().toLowerCase() | |
| switch (sanitizedOsType) { | |
| // Значения, представленные в документации os.type(): | |
| case "windows_nt": return "win32" | |
| case "darwin": return "darwin" | |
| case "linux": return "linux" | |
| } | |
| return undefined | |
| } | |
| export function getOsArchitectureUsingPlatform(osPlatform: NodeJS.Platform | undefined): NodeJS.Architecture | undefined { | |
| const sanitizedOsMachine = os.machine().toLowerCase() | |
| switch (sanitizedOsMachine) { | |
| // Значения, представленные в документации os.machine(): | |
| case "arm": return "arm" | |
| case "arm64": return "arm64" | |
| case "aarch64": return "arm64" | |
| case "mips": return "mips" | |
| case "mips64": return "mips" | |
| case "ppc64": return "ppc64" | |
| case "ppc64le": return "ppc" | |
| case "s390": return "s390" | |
| case "s390x": return "s390x" | |
| case "i386": return "ia32" | |
| // Значение "i686" используется для обозначения x86 приложений, запущенных на x86_64 операционной системе: | |
| // https://github.com/nodejs/node/issues/56975#issuecomment-2650606500 | |
| // https://github.com/nodejs/node/blob/b07ff551db152ccb507e71160ce077e235206b16/deps/uv/src/win/util.c#L1685 | |
| case "i686": { | |
| // NodeJS имеет баг, не позволяющий в сборке под x86 точно определить разрядность операционной системы средствами его API | |
| // https://github.com/nodejs/node/issues/58493 | |
| const isWindows = osPlatform === "win32" | |
| if (isWindows) { | |
| const windowsOsArchitecture = getWindowsOsArchitectureUsingPlatform() | |
| return windowsOsArchitecture | |
| } | |
| return "x64" | |
| } | |
| case "x86_64": { | |
| // Экспериментально подтверждено, что os.machine() на Windows для arm64 для сборок под x86_64 | |
| // Возвращает значение x86_64, не соответствующее фактической архитектуре операционной системы | |
| const isWindows = osPlatform === "win32" | |
| if (isWindows) { | |
| const windowsOsArchitecture = getWindowsOsArchitectureUsingPlatform() | |
| return windowsOsArchitecture | |
| } | |
| return "x64" | |
| } | |
| // Остальные значения, возвращаемые реализацией NodeJS: | |
| // https://github.com/nodejs/node/blob/b07ff551db152ccb507e71160ce077e235206b16/deps/uv/src/win/util.c#L1667 | |
| // Неподдерживаемые значения: | |
| // 1) DEC Aplha: "alpha" | |
| // https://github.com/nodejs/node/blob/b07ff551db152ccb507e71160ce077e235206b16/deps/uv/src/win/util.c#L1692 | |
| // 2) SuperH: "shx" | |
| // https://github.com/nodejs/node/blob/b07ff551db152ccb507e71160ce077e235206b16/deps/uv/src/win/util.c#L1698 | |
| case "ia64": return "x64" | |
| case "powerpc": return "ppc" | |
| // Значения, оставшиеся в NodeJS.Architecture (включено на всякий случай): | |
| case "loong64": return "loong64" | |
| case "mipsel": return "mipsel" | |
| case "ppc": return "ppc" | |
| case "riscv64": return "riscv64" | |
| // Значения, выявленные экспериментально: | |
| // Значение "unknown" может использоваться виртуализированными системами (пр. на Windows 11 под arm64 в Parallels Desktop на MacOS под arm64) | |
| case "unknown": { | |
| const isWindows = osPlatform === "win32" | |
| if (isWindows) { | |
| const windowsOsArchitecture = getWindowsOsArchitectureUsingPlatform() | |
| return windowsOsArchitecture | |
| } | |
| return undefined | |
| } | |
| } | |
| return undefined | |
| } | |
| export function getOsArchitectureEnvVar(osPlatform: NodeJS.Platform | undefined): string | undefined { | |
| // Для лучшей точности в случае неопределенной платформы следует сначала обрабатывать переменные | |
| // среды, специфичные для каждой операционной системы, и только после переходить к общим навроде HOSTTYPE | |
| const isWindows = osPlatform === "win32" | |
| if (isWindows || !osPlatform) { | |
| const rawOsArchitecture = getWindowsOsArchitectureEnvVar() | |
| if (isWindows) return rawOsArchitecture | |
| const isMostLikelyWindows = !osPlatform && rawOsArchitecture | |
| if (isMostLikelyWindows) return rawOsArchitecture | |
| } | |
| const osTypeEnvVar = process.env["OSTYPE"] | |
| const isMacOs = osPlatform === "darwin" || (osTypeEnvVar?.startsWith("darwin") ?? false) | |
| if (isMacOs || !osPlatform) { | |
| // Экспериментально подтверждено, что MACHTYPE на MacOS для arm64 без использования Rosetta | |
| // возвращает значение x86_64, не соответствующее фактической архитектуре операционной системы | |
| const machTypeEnvVar = process.env["MACHTYPE"] | |
| const cpuTypeEnvVar = process.env["CPUTYPE"] | |
| const isValuesExpected = machTypeEnvVar && cpuTypeEnvVar && machTypeEnvVar.toLocaleLowerCase() === cpuTypeEnvVar.toLocaleLowerCase() | |
| const rawOsArchitecture = isValuesExpected ? machTypeEnvVar : cpuTypeEnvVar | |
| if (isMacOs) return rawOsArchitecture | |
| const isMostLikelyMacOs = !osPlatform && rawOsArchitecture | |
| if (isMostLikelyMacOs) return rawOsArchitecture | |
| } | |
| const isLinux = osPlatform === "linux" | |
| if (isLinux || !osPlatform) { | |
| const rawOsArchitecture = process.env["HOSTTYPE"] ?? process.env["MACHTYPE"] | |
| if (isLinux) return rawOsArchitecture | |
| const isMostLikelyLinux = !osPlatform && rawOsArchitecture | |
| if (isMostLikelyLinux) return rawOsArchitecture | |
| } | |
| return undefined | |
| } | |
| function getWindowsOsArchitectureUsingPlatform(): NodeJS.Architecture | undefined { | |
| const windowsOsArchitectureEnvVar = getWindowsOsArchitectureEnvVar() | |
| if (windowsOsArchitectureEnvVar === undefined) return undefined | |
| const sanitizedOsArchitectureEnvVar = windowsOsArchitectureEnvVar.toLowerCase() | |
| switch (sanitizedOsArchitectureEnvVar) { | |
| // Значения, представленные в документации win32: | |
| // https://learn.microsoft.com/en-us/windows/win32/winprog64/wow64-implementation-details#environment-variables | |
| case "amd64": { | |
| // Экспериментально подтверждено, что переменная PROCESSOR_ARCHITECTURE на Windows для arm64 для сборок под x86_64 | |
| // имеет значение AMD64, не соответствующее фактической архитектуре операционной системы | |
| const programFilesArmEnvVar = process.env["ProgramFiles(Arm)"] | |
| const isArm64 = programFilesArmEnvVar !== undefined | |
| if (isArm64) return "arm64" | |
| return "x64" | |
| } | |
| case "ia64": return "x64" | |
| case "arm64": return "arm64" | |
| case "x86": return "ia32" | |
| } | |
| return undefined | |
| } | |
| function getWindowsOsArchitectureEnvVar(): string | undefined { | |
| // Несмотря на название, переменная среды PROCESSOR_ARCHITECTURE хранит архитектуру операционной системы, а не | |
| // самого процессора (пр. на Windows на x86 на процессоре x86_64 переменная имеет значение `x86`) | |
| const osArchitectureEnvVar = process.env["PROCESSOR_ARCHITECTURE"] | |
| if (osArchitectureEnvVar === undefined) return undefined | |
| const sanitizedOsArchitectureEnvVar = osArchitectureEnvVar.toLowerCase() | |
| // При запуске 32-битного процесса (x86) на 64-битной операционной системе (x86_64, arm64) | |
| // реальное содержимое PROCESSOR_ARCHITECTURE содержится в PROCESSOR_ARCHITEW6432 | |
| // https://learn.microsoft.com/en-us/windows/win32/winprog64/wow64-implementation-details#environment-variables | |
| const is32BitProcess = sanitizedOsArchitectureEnvVar === "x86" | |
| if (is32BitProcess) { | |
| const wowCpuArchitectureEnvVar = process.env["PROCESSOR_ARCHITEW6432"] | |
| if (wowCpuArchitectureEnvVar) return wowCpuArchitectureEnvVar | |
| } | |
| return osArchitectureEnvVar | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment