thread-sleep-compat
Advanced tools
| /** | ||
| * Postinstall script for thread-sleep-compat | ||
| * | ||
| * Downloads all platform-specific native binaries for old Node versions (< 0.12) | ||
| * since we don't know which Node version will actually run this module. | ||
| */ | ||
| export {}; |
| /** | ||
| * Postinstall script for thread-sleep-compat | ||
| * | ||
| * Downloads all platform-specific native binaries for old Node versions (< 0.12) | ||
| * since we don't know which Node version will actually run this module. | ||
| */ | ||
| export {}; |
| /** | ||
| * Postinstall script for thread-sleep-compat | ||
| * | ||
| * Downloads all platform-specific native binaries for old Node versions (< 0.12) | ||
| * since we don't know which Node version will actually run this module. | ||
| */ "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { | ||
| value: true | ||
| }); | ||
| var _child_process = require("child_process"); | ||
| var _exitcompat = /*#__PURE__*/ _interop_require_default(require("exit-compat")); | ||
| var _fs = /*#__PURE__*/ _interop_require_default(require("fs")); | ||
| var _mkdirpclassic = /*#__PURE__*/ _interop_require_default(require("mkdirp-classic")); | ||
| var _module = /*#__PURE__*/ _interop_require_default(require("module")); | ||
| var _os = /*#__PURE__*/ _interop_require_default(require("os")); | ||
| var _path = /*#__PURE__*/ _interop_require_default(require("path")); | ||
| var _url = /*#__PURE__*/ _interop_require_default(require("url")); | ||
| function _interop_require_default(obj) { | ||
| return obj && obj.__esModule ? obj : { | ||
| default: obj | ||
| }; | ||
| } | ||
| // CJS/ESM compatibility | ||
| var _require = typeof require === 'undefined' ? _module.default.createRequire(require("url").pathToFileURL(__filename).toString()) : require; | ||
| var __dirname = _path.default.dirname(typeof __filename !== 'undefined' ? __filename : _url.default.fileURLToPath(require("url").pathToFileURL(__filename).toString())); | ||
| // Configuration | ||
| var GITHUB_REPO = 'kmalakoff/thread-sleep-compat'; | ||
| // Path is relative to dist/cjs/scripts/ at runtime | ||
| var root = _path.default.join(__dirname, '..', '..', '..'); | ||
| var pkg = _require(_path.default.join(root, 'package.json')); | ||
| var BINARIES_VERSION = pkg.binaryVersion; | ||
| // ABI versions needed for Node < 0.12 (normalized to decimal strings) | ||
| // ABI 1: Node 0.8.x and earlier | ||
| // ABI 11: Node 0.10.x | ||
| // Note: ABI 14 (Node 0.11.x) skipped - unstable dev branch, not widely used | ||
| var ABI_VERSIONS = [ | ||
| 'v1', | ||
| 'v11' | ||
| ]; | ||
| /** | ||
| * Get ALL architectures for the current platform | ||
| * Old Node versions may run under emulation (Rosetta, QEMU, WoW64) | ||
| * so we download all available binaries for the platform | ||
| */ function getArchitectures() { | ||
| var platform = _os.default.platform(); | ||
| if (platform === 'darwin') { | ||
| return [ | ||
| 'arm64', | ||
| 'x64' | ||
| ]; | ||
| } | ||
| if (platform === 'linux') { | ||
| return [ | ||
| 'arm64', | ||
| 'arm', | ||
| 'x64' | ||
| ]; | ||
| } | ||
| if (platform === 'win32') { | ||
| return [ | ||
| 'ia32', | ||
| 'x64' | ||
| ]; | ||
| } | ||
| // Fallback to current arch for unknown platforms | ||
| return [ | ||
| _os.default.arch() | ||
| ]; | ||
| } | ||
| /** | ||
| * Get the download URL for the binary archive | ||
| */ function getDownloadUrl(abiVersion, arch) { | ||
| var platform = _os.default.platform(); | ||
| var filename = [ | ||
| pkg.name, | ||
| 'node', | ||
| abiVersion, | ||
| platform, | ||
| arch | ||
| ].join('-'); | ||
| var archiveName = "".concat(filename, ".tar.gz"); | ||
| return { | ||
| url: "https://github.com/".concat(GITHUB_REPO, "/releases/download/binaries-v").concat(BINARIES_VERSION, "/").concat(archiveName), | ||
| filename: filename | ||
| }; | ||
| } | ||
| /** | ||
| * Get temp directory (compatible with Node 0.8) | ||
| */ function getTmpDir() { | ||
| return typeof _os.default.tmpdir === 'function' ? _os.default.tmpdir() : process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp'; | ||
| } | ||
| /** | ||
| * Download using curl (macOS, Linux, Windows 10+) | ||
| */ function downloadWithCurl(downloadUrl, destPath, callback) { | ||
| var curl = (0, _child_process.spawn)('curl', [ | ||
| '-L', | ||
| '-f', | ||
| '-s', | ||
| '-o', | ||
| destPath, | ||
| downloadUrl | ||
| ]); | ||
| curl.on('close', function(code) { | ||
| if (code !== 0) { | ||
| // curl exit codes: 22 = HTTP error (4xx/5xx), 56 = receive error (often 404 with -f) | ||
| if (code === 22 || code === 56) { | ||
| callback(new Error('HTTP 404')); | ||
| } else { | ||
| callback(new Error("curl failed with exit code ".concat(code))); | ||
| } | ||
| return; | ||
| } | ||
| callback(null); | ||
| }); | ||
| curl.on('error', function(err) { | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Download using PowerShell (Windows 7+ fallback) | ||
| */ function downloadWithPowerShell(downloadUrl, destPath, callback) { | ||
| var psCommand = 'Invoke-WebRequest -Uri "'.concat(downloadUrl, '" -OutFile "').concat(destPath, '" -UseBasicParsing'); | ||
| var ps = (0, _child_process.spawn)('powershell', [ | ||
| '-NoProfile', | ||
| '-Command', | ||
| psCommand | ||
| ]); | ||
| ps.on('close', function(code) { | ||
| if (code !== 0) { | ||
| callback(new Error("PowerShell download failed with exit code ".concat(code))); | ||
| return; | ||
| } | ||
| callback(null); | ||
| }); | ||
| ps.on('error', function(err) { | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Download a file - tries curl first, falls back to PowerShell on Windows | ||
| * Node 0.8's OpenSSL doesn't support TLS 1.2+ required by GitHub | ||
| */ function downloadFile(downloadUrl, destPath, callback) { | ||
| downloadWithCurl(downloadUrl, destPath, function(err) { | ||
| var _err_message; | ||
| if (!err) { | ||
| callback(null); | ||
| return; | ||
| } | ||
| // If curl failed and we're on Windows, try PowerShell | ||
| if (_os.default.platform() === 'win32' && (err === null || err === void 0 ? void 0 : (_err_message = err.message) === null || _err_message === void 0 ? void 0 : _err_message.indexOf('ENOENT')) >= 0) { | ||
| downloadWithPowerShell(downloadUrl, destPath, callback); | ||
| return; | ||
| } | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Extract tar.gz archive | ||
| * Available on: macOS, Linux, Windows 10+ | ||
| */ function extractArchive(archivePath, destDir, callback) { | ||
| var tar = (0, _child_process.spawn)('tar', [ | ||
| '-xzf', | ||
| archivePath, | ||
| '-C', | ||
| destDir | ||
| ]); | ||
| tar.on('close', function(code) { | ||
| if (code !== 0) { | ||
| callback(new Error("tar failed with exit code ".concat(code))); | ||
| return; | ||
| } | ||
| callback(null); | ||
| }); | ||
| tar.on('error', function(err) { | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Download and extract a single binary | ||
| */ function downloadBinary(abiVersion, arch, outDir, callback) { | ||
| var info = getDownloadUrl(abiVersion, arch); | ||
| var destDir = _path.default.join(outDir, info.filename); | ||
| // Check if binary already exists | ||
| var bindingPath = _path.default.join(destDir, 'build', 'Release', 'thread_sleep.node'); | ||
| if (_fs.default.existsSync(bindingPath)) { | ||
| callback(null, 'exists'); | ||
| return; | ||
| } | ||
| var tempPath = _path.default.join(getTmpDir(), "thread-sleep-compat-".concat(abiVersion, "-").concat(arch, "-").concat(Date.now(), ".tar.gz")); | ||
| downloadFile(info.url, tempPath, function(downloadErr) { | ||
| if (downloadErr) { | ||
| // Clean up temp file if it exists | ||
| if (_fs.default.existsSync(tempPath)) { | ||
| try { | ||
| _fs.default.unlinkSync(tempPath); | ||
| } catch (_e) { | ||
| // ignore | ||
| } | ||
| } | ||
| callback(downloadErr); | ||
| return; | ||
| } | ||
| // Create destination directory before extracting | ||
| _mkdirpclassic.default.sync(destDir); | ||
| extractArchive(tempPath, destDir, function(extractErr) { | ||
| // Clean up temp file | ||
| if (_fs.default.existsSync(tempPath)) { | ||
| try { | ||
| _fs.default.unlinkSync(tempPath); | ||
| } catch (_e) { | ||
| // ignore | ||
| } | ||
| } | ||
| if (extractErr) { | ||
| callback(extractErr); | ||
| return; | ||
| } | ||
| callback(null, 'downloaded'); | ||
| }); | ||
| }); | ||
| } | ||
| /** | ||
| * Build list of all downloads needed (ABIs × architectures) | ||
| */ function getDownloadList() { | ||
| var archs = getArchitectures(); | ||
| var downloads = []; | ||
| for(var i = 0; i < ABI_VERSIONS.length; i++){ | ||
| for(var j = 0; j < archs.length; j++){ | ||
| downloads.push({ | ||
| abi: ABI_VERSIONS[i], | ||
| arch: archs[j] | ||
| }); | ||
| } | ||
| } | ||
| return downloads; | ||
| } | ||
| /** | ||
| * Download binaries sequentially (callback-based for Node 0.8 compat) | ||
| */ function downloadAll(downloads, outDir, index, results, callback) { | ||
| if (index >= downloads.length) { | ||
| callback(null, results); | ||
| return; | ||
| } | ||
| var item = downloads[index]; | ||
| console.log("postinstall: Downloading binary for ABI ".concat(item.abi, " (").concat(item.arch, ")...")); | ||
| downloadBinary(item.abi, item.arch, outDir, function(err, status) { | ||
| if (err) { | ||
| results.push({ | ||
| abi: item.abi, | ||
| arch: item.arch, | ||
| error: err.message || String(err) | ||
| }); | ||
| } else { | ||
| results.push({ | ||
| abi: item.abi, | ||
| arch: item.arch, | ||
| status: status | ||
| }); | ||
| } | ||
| downloadAll(downloads, outDir, index + 1, results, callback); | ||
| }); | ||
| } | ||
| /** | ||
| * Main installation function | ||
| */ function main() { | ||
| var platform = _os.default.platform(); | ||
| var archs = getArchitectures(); | ||
| console.log("postinstall: Installing thread-sleep-compat binaries for ".concat(platform, " (").concat(archs.join(', '), ")")); | ||
| var outDir = _path.default.join(root, 'out'); | ||
| // Create output directory | ||
| _mkdirpclassic.default.sync(outDir); | ||
| var downloads = getDownloadList(); | ||
| downloadAll(downloads, outDir, 0, [], function(_err, results) { | ||
| var succeeded = 0; | ||
| var failed = 0; | ||
| var existed = 0; | ||
| for(var i = 0; i < results.length; i++){ | ||
| var r = results[i]; | ||
| if (r.error) { | ||
| failed++; | ||
| if (r.error.indexOf('404') >= 0) { | ||
| console.log("postinstall: Binary for ".concat(r.abi, "-").concat(r.arch, " not available")); | ||
| } else { | ||
| console.log("postinstall: Failed to download ".concat(r.abi, "-").concat(r.arch, ": ").concat(r.error)); | ||
| } | ||
| } else if (r.status === 'exists') { | ||
| existed++; | ||
| } else { | ||
| succeeded++; | ||
| } | ||
| } | ||
| if (succeeded > 0) { | ||
| console.log("postinstall: Downloaded ".concat(succeeded, " binary(ies)")); | ||
| } | ||
| if (existed > 0) { | ||
| console.log("postinstall: ".concat(existed, " binary(ies) already existed")); | ||
| } | ||
| if (failed === results.length) { | ||
| console.log(''); | ||
| console.log("postinstall: No binaries available for ".concat(platform)); | ||
| console.log('thread-sleep-compat will work on Node >= 0.12 but not on older versions.'); | ||
| } | ||
| (0, _exitcompat.default)(0); | ||
| }); | ||
| } | ||
| main(); | ||
| /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; } |
| {"version":3,"sources":["/Users/kevin/Dev/OpenSource/compat/thread-sleep-compat/src/scripts/postinstall.ts"],"sourcesContent":["/**\n * Postinstall script for thread-sleep-compat\n *\n * Downloads all platform-specific native binaries for old Node versions (< 0.12)\n * since we don't know which Node version will actually run this module.\n */\n\nimport { spawn } from 'child_process';\nimport exit from 'exit-compat';\nimport fs from 'fs';\nimport mkdirp from 'mkdirp-classic';\nimport Module from 'module';\nimport os from 'os';\nimport path from 'path';\nimport url from 'url';\n\n// CJS/ESM compatibility\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\nconst __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename : url.fileURLToPath(import.meta.url));\n\n// Configuration\nconst GITHUB_REPO = 'kmalakoff/thread-sleep-compat';\n// Path is relative to dist/cjs/scripts/ at runtime\nconst root = path.join(__dirname, '..', '..', '..');\nconst pkg = _require(path.join(root, 'package.json'));\nconst BINARIES_VERSION = pkg.binaryVersion;\n\n// ABI versions needed for Node < 0.12 (normalized to decimal strings)\n// ABI 1: Node 0.8.x and earlier\n// ABI 11: Node 0.10.x\n// Note: ABI 14 (Node 0.11.x) skipped - unstable dev branch, not widely used\nconst ABI_VERSIONS = ['v1', 'v11'];\n\ntype Callback = (err?: Error | null, status?: string) => void;\ntype ResultsCallback = (err: Error | null, results: DownloadResult[]) => void;\n\ninterface DownloadInfo {\n url: string;\n filename: string;\n}\n\ninterface DownloadItem {\n abi: string;\n arch: string;\n}\n\ninterface DownloadResult {\n abi: string;\n arch: string;\n status?: string;\n error?: string;\n}\n\n/**\n * Get ALL architectures for the current platform\n * Old Node versions may run under emulation (Rosetta, QEMU, WoW64)\n * so we download all available binaries for the platform\n */\nfunction getArchitectures(): string[] {\n const platform = os.platform();\n\n if (platform === 'darwin') {\n return ['arm64', 'x64'];\n }\n if (platform === 'linux') {\n return ['arm64', 'arm', 'x64'];\n }\n if (platform === 'win32') {\n return ['ia32', 'x64'];\n }\n\n // Fallback to current arch for unknown platforms\n return [os.arch()];\n}\n\n/**\n * Get the download URL for the binary archive\n */\nfunction getDownloadUrl(abiVersion: string, arch: string): DownloadInfo {\n const platform = os.platform();\n const filename = [pkg.name, 'node', abiVersion, platform, arch].join('-');\n const archiveName = `${filename}.tar.gz`;\n return {\n url: `https://github.com/${GITHUB_REPO}/releases/download/binaries-v${BINARIES_VERSION}/${archiveName}`,\n filename,\n };\n}\n\n/**\n * Get temp directory (compatible with Node 0.8)\n */\nfunction getTmpDir(): string {\n return typeof os.tmpdir === 'function' ? os.tmpdir() : process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp';\n}\n\n/**\n * Download using curl (macOS, Linux, Windows 10+)\n */\nfunction downloadWithCurl(downloadUrl: string, destPath: string, callback: Callback): void {\n const curl = spawn('curl', ['-L', '-f', '-s', '-o', destPath, downloadUrl]);\n\n curl.on('close', (code) => {\n if (code !== 0) {\n // curl exit codes: 22 = HTTP error (4xx/5xx), 56 = receive error (often 404 with -f)\n if (code === 22 || code === 56) {\n callback(new Error('HTTP 404'));\n } else {\n callback(new Error(`curl failed with exit code ${code}`));\n }\n return;\n }\n callback(null);\n });\n\n curl.on('error', (err) => {\n callback(err);\n });\n}\n\n/**\n * Download using PowerShell (Windows 7+ fallback)\n */\nfunction downloadWithPowerShell(downloadUrl: string, destPath: string, callback: Callback): void {\n const psCommand = `Invoke-WebRequest -Uri \"${downloadUrl}\" -OutFile \"${destPath}\" -UseBasicParsing`;\n const ps = spawn('powershell', ['-NoProfile', '-Command', psCommand]);\n\n ps.on('close', (code) => {\n if (code !== 0) {\n callback(new Error(`PowerShell download failed with exit code ${code}`));\n return;\n }\n callback(null);\n });\n\n ps.on('error', (err) => {\n callback(err);\n });\n}\n\n/**\n * Download a file - tries curl first, falls back to PowerShell on Windows\n * Node 0.8's OpenSSL doesn't support TLS 1.2+ required by GitHub\n */\nfunction downloadFile(downloadUrl: string, destPath: string, callback: Callback): void {\n downloadWithCurl(downloadUrl, destPath, (err) => {\n if (!err) {\n callback(null);\n return;\n }\n\n // If curl failed and we're on Windows, try PowerShell\n if (os.platform() === 'win32' && err?.message?.indexOf('ENOENT') >= 0) {\n downloadWithPowerShell(downloadUrl, destPath, callback);\n return;\n }\n\n callback(err);\n });\n}\n\n/**\n * Extract tar.gz archive\n * Available on: macOS, Linux, Windows 10+\n */\nfunction extractArchive(archivePath: string, destDir: string, callback: Callback): void {\n const tar = spawn('tar', ['-xzf', archivePath, '-C', destDir]);\n tar.on('close', (code) => {\n if (code !== 0) {\n callback(new Error(`tar failed with exit code ${code}`));\n return;\n }\n callback(null);\n });\n tar.on('error', (err) => {\n callback(err);\n });\n}\n\n/**\n * Download and extract a single binary\n */\nfunction downloadBinary(abiVersion: string, arch: string, outDir: string, callback: Callback): void {\n const info = getDownloadUrl(abiVersion, arch);\n const destDir = path.join(outDir, info.filename);\n\n // Check if binary already exists\n const bindingPath = path.join(destDir, 'build', 'Release', 'thread_sleep.node');\n if (fs.existsSync(bindingPath)) {\n callback(null, 'exists');\n return;\n }\n\n const tempPath = path.join(getTmpDir(), `thread-sleep-compat-${abiVersion}-${arch}-${Date.now()}.tar.gz`);\n\n downloadFile(info.url, tempPath, (downloadErr) => {\n if (downloadErr) {\n // Clean up temp file if it exists\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (_e) {\n // ignore\n }\n }\n callback(downloadErr);\n return;\n }\n\n // Create destination directory before extracting\n mkdirp.sync(destDir);\n\n extractArchive(tempPath, destDir, (extractErr) => {\n // Clean up temp file\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (_e) {\n // ignore\n }\n }\n\n if (extractErr) {\n callback(extractErr);\n return;\n }\n\n callback(null, 'downloaded');\n });\n });\n}\n\n/**\n * Build list of all downloads needed (ABIs × architectures)\n */\nfunction getDownloadList(): DownloadItem[] {\n const archs = getArchitectures();\n const downloads: DownloadItem[] = [];\n for (let i = 0; i < ABI_VERSIONS.length; i++) {\n for (let j = 0; j < archs.length; j++) {\n downloads.push({ abi: ABI_VERSIONS[i], arch: archs[j] });\n }\n }\n return downloads;\n}\n\n/**\n * Download binaries sequentially (callback-based for Node 0.8 compat)\n */\nfunction downloadAll(downloads: DownloadItem[], outDir: string, index: number, results: DownloadResult[], callback: ResultsCallback): void {\n if (index >= downloads.length) {\n callback(null, results);\n return;\n }\n\n const item = downloads[index];\n console.log(`postinstall: Downloading binary for ABI ${item.abi} (${item.arch})...`);\n\n downloadBinary(item.abi, item.arch, outDir, (err, status) => {\n if (err) {\n results.push({ abi: item.abi, arch: item.arch, error: err.message || String(err) });\n } else {\n results.push({ abi: item.abi, arch: item.arch, status });\n }\n downloadAll(downloads, outDir, index + 1, results, callback);\n });\n}\n\n/**\n * Main installation function\n */\nfunction main(): void {\n const platform = os.platform();\n const archs = getArchitectures();\n\n console.log(`postinstall: Installing thread-sleep-compat binaries for ${platform} (${archs.join(', ')})`);\n\n const outDir = path.join(root, 'out');\n\n // Create output directory\n mkdirp.sync(outDir);\n\n const downloads = getDownloadList();\n\n downloadAll(downloads, outDir, 0, [], (_err, results) => {\n let succeeded = 0;\n let failed = 0;\n let existed = 0;\n\n for (let i = 0; i < results.length; i++) {\n const r = results[i];\n if (r.error) {\n failed++;\n if (r.error.indexOf('404') >= 0) {\n console.log(`postinstall: Binary for ${r.abi}-${r.arch} not available`);\n } else {\n console.log(`postinstall: Failed to download ${r.abi}-${r.arch}: ${r.error}`);\n }\n } else if (r.status === 'exists') {\n existed++;\n } else {\n succeeded++;\n }\n }\n\n if (succeeded > 0) {\n console.log(`postinstall: Downloaded ${succeeded} binary(ies)`);\n }\n if (existed > 0) {\n console.log(`postinstall: ${existed} binary(ies) already existed`);\n }\n if (failed === results.length) {\n console.log('');\n console.log(`postinstall: No binaries available for ${platform}`);\n console.log('thread-sleep-compat will work on Node >= 0.12 but not on older versions.');\n }\n\n exit(0);\n });\n}\n\nmain();\n"],"names":["_require","require","Module","createRequire","__dirname","path","dirname","__filename","url","fileURLToPath","GITHUB_REPO","root","join","pkg","BINARIES_VERSION","binaryVersion","ABI_VERSIONS","getArchitectures","platform","os","arch","getDownloadUrl","abiVersion","filename","name","archiveName","getTmpDir","tmpdir","process","env","TMPDIR","TMP","TEMP","downloadWithCurl","downloadUrl","destPath","callback","curl","spawn","on","code","Error","err","downloadWithPowerShell","psCommand","ps","downloadFile","message","indexOf","extractArchive","archivePath","destDir","tar","downloadBinary","outDir","info","bindingPath","fs","existsSync","tempPath","Date","now","downloadErr","unlinkSync","_e","mkdirp","sync","extractErr","getDownloadList","archs","downloads","i","length","j","push","abi","downloadAll","index","results","item","console","log","status","error","String","main","_err","succeeded","failed","existed","r","exit"],"mappings":"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"} |
| /** | ||
| * Postinstall script for thread-sleep-compat | ||
| * | ||
| * Downloads all platform-specific native binaries for old Node versions (< 0.12) | ||
| * since we don't know which Node version will actually run this module. | ||
| */ | ||
| export {}; |
| /** | ||
| * Postinstall script for thread-sleep-compat | ||
| * | ||
| * Downloads all platform-specific native binaries for old Node versions (< 0.12) | ||
| * since we don't know which Node version will actually run this module. | ||
| */ import { spawn } from 'child_process'; | ||
| import exit from 'exit-compat'; | ||
| import fs from 'fs'; | ||
| import mkdirp from 'mkdirp-classic'; | ||
| import Module from 'module'; | ||
| import os from 'os'; | ||
| import path from 'path'; | ||
| import url from 'url'; | ||
| // CJS/ESM compatibility | ||
| const _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require; | ||
| const __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename : url.fileURLToPath(import.meta.url)); | ||
| // Configuration | ||
| const GITHUB_REPO = 'kmalakoff/thread-sleep-compat'; | ||
| // Path is relative to dist/cjs/scripts/ at runtime | ||
| const root = path.join(__dirname, '..', '..', '..'); | ||
| const pkg = _require(path.join(root, 'package.json')); | ||
| const BINARIES_VERSION = pkg.binaryVersion; | ||
| // ABI versions needed for Node < 0.12 (normalized to decimal strings) | ||
| // ABI 1: Node 0.8.x and earlier | ||
| // ABI 11: Node 0.10.x | ||
| // Note: ABI 14 (Node 0.11.x) skipped - unstable dev branch, not widely used | ||
| const ABI_VERSIONS = [ | ||
| 'v1', | ||
| 'v11' | ||
| ]; | ||
| /** | ||
| * Get ALL architectures for the current platform | ||
| * Old Node versions may run under emulation (Rosetta, QEMU, WoW64) | ||
| * so we download all available binaries for the platform | ||
| */ function getArchitectures() { | ||
| const platform = os.platform(); | ||
| if (platform === 'darwin') { | ||
| return [ | ||
| 'arm64', | ||
| 'x64' | ||
| ]; | ||
| } | ||
| if (platform === 'linux') { | ||
| return [ | ||
| 'arm64', | ||
| 'arm', | ||
| 'x64' | ||
| ]; | ||
| } | ||
| if (platform === 'win32') { | ||
| return [ | ||
| 'ia32', | ||
| 'x64' | ||
| ]; | ||
| } | ||
| // Fallback to current arch for unknown platforms | ||
| return [ | ||
| os.arch() | ||
| ]; | ||
| } | ||
| /** | ||
| * Get the download URL for the binary archive | ||
| */ function getDownloadUrl(abiVersion, arch) { | ||
| const platform = os.platform(); | ||
| const filename = [ | ||
| pkg.name, | ||
| 'node', | ||
| abiVersion, | ||
| platform, | ||
| arch | ||
| ].join('-'); | ||
| const archiveName = `${filename}.tar.gz`; | ||
| return { | ||
| url: `https://github.com/${GITHUB_REPO}/releases/download/binaries-v${BINARIES_VERSION}/${archiveName}`, | ||
| filename | ||
| }; | ||
| } | ||
| /** | ||
| * Get temp directory (compatible with Node 0.8) | ||
| */ function getTmpDir() { | ||
| return typeof os.tmpdir === 'function' ? os.tmpdir() : process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp'; | ||
| } | ||
| /** | ||
| * Download using curl (macOS, Linux, Windows 10+) | ||
| */ function downloadWithCurl(downloadUrl, destPath, callback) { | ||
| const curl = spawn('curl', [ | ||
| '-L', | ||
| '-f', | ||
| '-s', | ||
| '-o', | ||
| destPath, | ||
| downloadUrl | ||
| ]); | ||
| curl.on('close', (code)=>{ | ||
| if (code !== 0) { | ||
| // curl exit codes: 22 = HTTP error (4xx/5xx), 56 = receive error (often 404 with -f) | ||
| if (code === 22 || code === 56) { | ||
| callback(new Error('HTTP 404')); | ||
| } else { | ||
| callback(new Error(`curl failed with exit code ${code}`)); | ||
| } | ||
| return; | ||
| } | ||
| callback(null); | ||
| }); | ||
| curl.on('error', (err)=>{ | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Download using PowerShell (Windows 7+ fallback) | ||
| */ function downloadWithPowerShell(downloadUrl, destPath, callback) { | ||
| const psCommand = `Invoke-WebRequest -Uri "${downloadUrl}" -OutFile "${destPath}" -UseBasicParsing`; | ||
| const ps = spawn('powershell', [ | ||
| '-NoProfile', | ||
| '-Command', | ||
| psCommand | ||
| ]); | ||
| ps.on('close', (code)=>{ | ||
| if (code !== 0) { | ||
| callback(new Error(`PowerShell download failed with exit code ${code}`)); | ||
| return; | ||
| } | ||
| callback(null); | ||
| }); | ||
| ps.on('error', (err)=>{ | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Download a file - tries curl first, falls back to PowerShell on Windows | ||
| * Node 0.8's OpenSSL doesn't support TLS 1.2+ required by GitHub | ||
| */ function downloadFile(downloadUrl, destPath, callback) { | ||
| downloadWithCurl(downloadUrl, destPath, (err)=>{ | ||
| var _err_message; | ||
| if (!err) { | ||
| callback(null); | ||
| return; | ||
| } | ||
| // If curl failed and we're on Windows, try PowerShell | ||
| if (os.platform() === 'win32' && (err === null || err === void 0 ? void 0 : (_err_message = err.message) === null || _err_message === void 0 ? void 0 : _err_message.indexOf('ENOENT')) >= 0) { | ||
| downloadWithPowerShell(downloadUrl, destPath, callback); | ||
| return; | ||
| } | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Extract tar.gz archive | ||
| * Available on: macOS, Linux, Windows 10+ | ||
| */ function extractArchive(archivePath, destDir, callback) { | ||
| const tar = spawn('tar', [ | ||
| '-xzf', | ||
| archivePath, | ||
| '-C', | ||
| destDir | ||
| ]); | ||
| tar.on('close', (code)=>{ | ||
| if (code !== 0) { | ||
| callback(new Error(`tar failed with exit code ${code}`)); | ||
| return; | ||
| } | ||
| callback(null); | ||
| }); | ||
| tar.on('error', (err)=>{ | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Download and extract a single binary | ||
| */ function downloadBinary(abiVersion, arch, outDir, callback) { | ||
| const info = getDownloadUrl(abiVersion, arch); | ||
| const destDir = path.join(outDir, info.filename); | ||
| // Check if binary already exists | ||
| const bindingPath = path.join(destDir, 'build', 'Release', 'thread_sleep.node'); | ||
| if (fs.existsSync(bindingPath)) { | ||
| callback(null, 'exists'); | ||
| return; | ||
| } | ||
| const tempPath = path.join(getTmpDir(), `thread-sleep-compat-${abiVersion}-${arch}-${Date.now()}.tar.gz`); | ||
| downloadFile(info.url, tempPath, (downloadErr)=>{ | ||
| if (downloadErr) { | ||
| // Clean up temp file if it exists | ||
| if (fs.existsSync(tempPath)) { | ||
| try { | ||
| fs.unlinkSync(tempPath); | ||
| } catch (_e) { | ||
| // ignore | ||
| } | ||
| } | ||
| callback(downloadErr); | ||
| return; | ||
| } | ||
| // Create destination directory before extracting | ||
| mkdirp.sync(destDir); | ||
| extractArchive(tempPath, destDir, (extractErr)=>{ | ||
| // Clean up temp file | ||
| if (fs.existsSync(tempPath)) { | ||
| try { | ||
| fs.unlinkSync(tempPath); | ||
| } catch (_e) { | ||
| // ignore | ||
| } | ||
| } | ||
| if (extractErr) { | ||
| callback(extractErr); | ||
| return; | ||
| } | ||
| callback(null, 'downloaded'); | ||
| }); | ||
| }); | ||
| } | ||
| /** | ||
| * Build list of all downloads needed (ABIs × architectures) | ||
| */ function getDownloadList() { | ||
| const archs = getArchitectures(); | ||
| const downloads = []; | ||
| for(let i = 0; i < ABI_VERSIONS.length; i++){ | ||
| for(let j = 0; j < archs.length; j++){ | ||
| downloads.push({ | ||
| abi: ABI_VERSIONS[i], | ||
| arch: archs[j] | ||
| }); | ||
| } | ||
| } | ||
| return downloads; | ||
| } | ||
| /** | ||
| * Download binaries sequentially (callback-based for Node 0.8 compat) | ||
| */ function downloadAll(downloads, outDir, index, results, callback) { | ||
| if (index >= downloads.length) { | ||
| callback(null, results); | ||
| return; | ||
| } | ||
| const item = downloads[index]; | ||
| console.log(`postinstall: Downloading binary for ABI ${item.abi} (${item.arch})...`); | ||
| downloadBinary(item.abi, item.arch, outDir, (err, status)=>{ | ||
| if (err) { | ||
| results.push({ | ||
| abi: item.abi, | ||
| arch: item.arch, | ||
| error: err.message || String(err) | ||
| }); | ||
| } else { | ||
| results.push({ | ||
| abi: item.abi, | ||
| arch: item.arch, | ||
| status | ||
| }); | ||
| } | ||
| downloadAll(downloads, outDir, index + 1, results, callback); | ||
| }); | ||
| } | ||
| /** | ||
| * Main installation function | ||
| */ function main() { | ||
| const platform = os.platform(); | ||
| const archs = getArchitectures(); | ||
| console.log(`postinstall: Installing thread-sleep-compat binaries for ${platform} (${archs.join(', ')})`); | ||
| const outDir = path.join(root, 'out'); | ||
| // Create output directory | ||
| mkdirp.sync(outDir); | ||
| const downloads = getDownloadList(); | ||
| downloadAll(downloads, outDir, 0, [], (_err, results)=>{ | ||
| let succeeded = 0; | ||
| let failed = 0; | ||
| let existed = 0; | ||
| for(let i = 0; i < results.length; i++){ | ||
| const r = results[i]; | ||
| if (r.error) { | ||
| failed++; | ||
| if (r.error.indexOf('404') >= 0) { | ||
| console.log(`postinstall: Binary for ${r.abi}-${r.arch} not available`); | ||
| } else { | ||
| console.log(`postinstall: Failed to download ${r.abi}-${r.arch}: ${r.error}`); | ||
| } | ||
| } else if (r.status === 'exists') { | ||
| existed++; | ||
| } else { | ||
| succeeded++; | ||
| } | ||
| } | ||
| if (succeeded > 0) { | ||
| console.log(`postinstall: Downloaded ${succeeded} binary(ies)`); | ||
| } | ||
| if (existed > 0) { | ||
| console.log(`postinstall: ${existed} binary(ies) already existed`); | ||
| } | ||
| if (failed === results.length) { | ||
| console.log(''); | ||
| console.log(`postinstall: No binaries available for ${platform}`); | ||
| console.log('thread-sleep-compat will work on Node >= 0.12 but not on older versions.'); | ||
| } | ||
| exit(0); | ||
| }); | ||
| } | ||
| main(); |
| {"version":3,"sources":["/Users/kevin/Dev/OpenSource/compat/thread-sleep-compat/src/scripts/postinstall.ts"],"sourcesContent":["/**\n * Postinstall script for thread-sleep-compat\n *\n * Downloads all platform-specific native binaries for old Node versions (< 0.12)\n * since we don't know which Node version will actually run this module.\n */\n\nimport { spawn } from 'child_process';\nimport exit from 'exit-compat';\nimport fs from 'fs';\nimport mkdirp from 'mkdirp-classic';\nimport Module from 'module';\nimport os from 'os';\nimport path from 'path';\nimport url from 'url';\n\n// CJS/ESM compatibility\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\nconst __dirname = path.dirname(typeof __filename !== 'undefined' ? __filename : url.fileURLToPath(import.meta.url));\n\n// Configuration\nconst GITHUB_REPO = 'kmalakoff/thread-sleep-compat';\n// Path is relative to dist/cjs/scripts/ at runtime\nconst root = path.join(__dirname, '..', '..', '..');\nconst pkg = _require(path.join(root, 'package.json'));\nconst BINARIES_VERSION = pkg.binaryVersion;\n\n// ABI versions needed for Node < 0.12 (normalized to decimal strings)\n// ABI 1: Node 0.8.x and earlier\n// ABI 11: Node 0.10.x\n// Note: ABI 14 (Node 0.11.x) skipped - unstable dev branch, not widely used\nconst ABI_VERSIONS = ['v1', 'v11'];\n\ntype Callback = (err?: Error | null, status?: string) => void;\ntype ResultsCallback = (err: Error | null, results: DownloadResult[]) => void;\n\ninterface DownloadInfo {\n url: string;\n filename: string;\n}\n\ninterface DownloadItem {\n abi: string;\n arch: string;\n}\n\ninterface DownloadResult {\n abi: string;\n arch: string;\n status?: string;\n error?: string;\n}\n\n/**\n * Get ALL architectures for the current platform\n * Old Node versions may run under emulation (Rosetta, QEMU, WoW64)\n * so we download all available binaries for the platform\n */\nfunction getArchitectures(): string[] {\n const platform = os.platform();\n\n if (platform === 'darwin') {\n return ['arm64', 'x64'];\n }\n if (platform === 'linux') {\n return ['arm64', 'arm', 'x64'];\n }\n if (platform === 'win32') {\n return ['ia32', 'x64'];\n }\n\n // Fallback to current arch for unknown platforms\n return [os.arch()];\n}\n\n/**\n * Get the download URL for the binary archive\n */\nfunction getDownloadUrl(abiVersion: string, arch: string): DownloadInfo {\n const platform = os.platform();\n const filename = [pkg.name, 'node', abiVersion, platform, arch].join('-');\n const archiveName = `${filename}.tar.gz`;\n return {\n url: `https://github.com/${GITHUB_REPO}/releases/download/binaries-v${BINARIES_VERSION}/${archiveName}`,\n filename,\n };\n}\n\n/**\n * Get temp directory (compatible with Node 0.8)\n */\nfunction getTmpDir(): string {\n return typeof os.tmpdir === 'function' ? os.tmpdir() : process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp';\n}\n\n/**\n * Download using curl (macOS, Linux, Windows 10+)\n */\nfunction downloadWithCurl(downloadUrl: string, destPath: string, callback: Callback): void {\n const curl = spawn('curl', ['-L', '-f', '-s', '-o', destPath, downloadUrl]);\n\n curl.on('close', (code) => {\n if (code !== 0) {\n // curl exit codes: 22 = HTTP error (4xx/5xx), 56 = receive error (often 404 with -f)\n if (code === 22 || code === 56) {\n callback(new Error('HTTP 404'));\n } else {\n callback(new Error(`curl failed with exit code ${code}`));\n }\n return;\n }\n callback(null);\n });\n\n curl.on('error', (err) => {\n callback(err);\n });\n}\n\n/**\n * Download using PowerShell (Windows 7+ fallback)\n */\nfunction downloadWithPowerShell(downloadUrl: string, destPath: string, callback: Callback): void {\n const psCommand = `Invoke-WebRequest -Uri \"${downloadUrl}\" -OutFile \"${destPath}\" -UseBasicParsing`;\n const ps = spawn('powershell', ['-NoProfile', '-Command', psCommand]);\n\n ps.on('close', (code) => {\n if (code !== 0) {\n callback(new Error(`PowerShell download failed with exit code ${code}`));\n return;\n }\n callback(null);\n });\n\n ps.on('error', (err) => {\n callback(err);\n });\n}\n\n/**\n * Download a file - tries curl first, falls back to PowerShell on Windows\n * Node 0.8's OpenSSL doesn't support TLS 1.2+ required by GitHub\n */\nfunction downloadFile(downloadUrl: string, destPath: string, callback: Callback): void {\n downloadWithCurl(downloadUrl, destPath, (err) => {\n if (!err) {\n callback(null);\n return;\n }\n\n // If curl failed and we're on Windows, try PowerShell\n if (os.platform() === 'win32' && err?.message?.indexOf('ENOENT') >= 0) {\n downloadWithPowerShell(downloadUrl, destPath, callback);\n return;\n }\n\n callback(err);\n });\n}\n\n/**\n * Extract tar.gz archive\n * Available on: macOS, Linux, Windows 10+\n */\nfunction extractArchive(archivePath: string, destDir: string, callback: Callback): void {\n const tar = spawn('tar', ['-xzf', archivePath, '-C', destDir]);\n tar.on('close', (code) => {\n if (code !== 0) {\n callback(new Error(`tar failed with exit code ${code}`));\n return;\n }\n callback(null);\n });\n tar.on('error', (err) => {\n callback(err);\n });\n}\n\n/**\n * Download and extract a single binary\n */\nfunction downloadBinary(abiVersion: string, arch: string, outDir: string, callback: Callback): void {\n const info = getDownloadUrl(abiVersion, arch);\n const destDir = path.join(outDir, info.filename);\n\n // Check if binary already exists\n const bindingPath = path.join(destDir, 'build', 'Release', 'thread_sleep.node');\n if (fs.existsSync(bindingPath)) {\n callback(null, 'exists');\n return;\n }\n\n const tempPath = path.join(getTmpDir(), `thread-sleep-compat-${abiVersion}-${arch}-${Date.now()}.tar.gz`);\n\n downloadFile(info.url, tempPath, (downloadErr) => {\n if (downloadErr) {\n // Clean up temp file if it exists\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (_e) {\n // ignore\n }\n }\n callback(downloadErr);\n return;\n }\n\n // Create destination directory before extracting\n mkdirp.sync(destDir);\n\n extractArchive(tempPath, destDir, (extractErr) => {\n // Clean up temp file\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (_e) {\n // ignore\n }\n }\n\n if (extractErr) {\n callback(extractErr);\n return;\n }\n\n callback(null, 'downloaded');\n });\n });\n}\n\n/**\n * Build list of all downloads needed (ABIs × architectures)\n */\nfunction getDownloadList(): DownloadItem[] {\n const archs = getArchitectures();\n const downloads: DownloadItem[] = [];\n for (let i = 0; i < ABI_VERSIONS.length; i++) {\n for (let j = 0; j < archs.length; j++) {\n downloads.push({ abi: ABI_VERSIONS[i], arch: archs[j] });\n }\n }\n return downloads;\n}\n\n/**\n * Download binaries sequentially (callback-based for Node 0.8 compat)\n */\nfunction downloadAll(downloads: DownloadItem[], outDir: string, index: number, results: DownloadResult[], callback: ResultsCallback): void {\n if (index >= downloads.length) {\n callback(null, results);\n return;\n }\n\n const item = downloads[index];\n console.log(`postinstall: Downloading binary for ABI ${item.abi} (${item.arch})...`);\n\n downloadBinary(item.abi, item.arch, outDir, (err, status) => {\n if (err) {\n results.push({ abi: item.abi, arch: item.arch, error: err.message || String(err) });\n } else {\n results.push({ abi: item.abi, arch: item.arch, status });\n }\n downloadAll(downloads, outDir, index + 1, results, callback);\n });\n}\n\n/**\n * Main installation function\n */\nfunction main(): void {\n const platform = os.platform();\n const archs = getArchitectures();\n\n console.log(`postinstall: Installing thread-sleep-compat binaries for ${platform} (${archs.join(', ')})`);\n\n const outDir = path.join(root, 'out');\n\n // Create output directory\n mkdirp.sync(outDir);\n\n const downloads = getDownloadList();\n\n downloadAll(downloads, outDir, 0, [], (_err, results) => {\n let succeeded = 0;\n let failed = 0;\n let existed = 0;\n\n for (let i = 0; i < results.length; i++) {\n const r = results[i];\n if (r.error) {\n failed++;\n if (r.error.indexOf('404') >= 0) {\n console.log(`postinstall: Binary for ${r.abi}-${r.arch} not available`);\n } else {\n console.log(`postinstall: Failed to download ${r.abi}-${r.arch}: ${r.error}`);\n }\n } else if (r.status === 'exists') {\n existed++;\n } else {\n succeeded++;\n }\n }\n\n if (succeeded > 0) {\n console.log(`postinstall: Downloaded ${succeeded} binary(ies)`);\n }\n if (existed > 0) {\n console.log(`postinstall: ${existed} binary(ies) already existed`);\n }\n if (failed === results.length) {\n console.log('');\n console.log(`postinstall: No binaries available for ${platform}`);\n console.log('thread-sleep-compat will work on Node >= 0.12 but not on older versions.');\n }\n\n exit(0);\n });\n}\n\nmain();\n"],"names":["spawn","exit","fs","mkdirp","Module","os","path","url","_require","require","createRequire","__dirname","dirname","__filename","fileURLToPath","GITHUB_REPO","root","join","pkg","BINARIES_VERSION","binaryVersion","ABI_VERSIONS","getArchitectures","platform","arch","getDownloadUrl","abiVersion","filename","name","archiveName","getTmpDir","tmpdir","process","env","TMPDIR","TMP","TEMP","downloadWithCurl","downloadUrl","destPath","callback","curl","on","code","Error","err","downloadWithPowerShell","psCommand","ps","downloadFile","message","indexOf","extractArchive","archivePath","destDir","tar","downloadBinary","outDir","info","bindingPath","existsSync","tempPath","Date","now","downloadErr","unlinkSync","_e","sync","extractErr","getDownloadList","archs","downloads","i","length","j","push","abi","downloadAll","index","results","item","console","log","status","error","String","main","_err","succeeded","failed","existed","r"],"mappings":"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"} |
+6
-6
| { | ||
| "name": "thread-sleep-compat", | ||
| "version": "1.1.1", | ||
| "version": "1.1.2", | ||
| "description": "thread-sleep the runs on multiple versions of node", | ||
@@ -50,11 +50,11 @@ "keywords": [ | ||
| "@types/mocha": "^10.0.10", | ||
| "@types/node": "^25.0.0", | ||
| "@types/node": "^25.0.1", | ||
| "cmake-js": "^7.4.0", | ||
| "cross-spawn-cb": "^2.4.10", | ||
| "fast-extract": "^1.8.12", | ||
| "nan": "2.14.2", | ||
| "node-version-use": "^2.1.0", | ||
| "fast-extract": "^1.8.13", | ||
| "nan": "2.24.0", | ||
| "node-version-use": "^2.1.3", | ||
| "prebuild": "^13.0.1", | ||
| "queue-cb": "^1.6.1", | ||
| "ts-dev-stack": "^1.21.2", | ||
| "ts-dev-stack": "^1.21.3", | ||
| "tsds-config": "^0.2.0" | ||
@@ -61,0 +61,0 @@ }, |
+6
-294
@@ -1,297 +0,9 @@ | ||
| /** | ||
| * Postinstall script for thread-sleep-compat | ||
| * | ||
| * Downloads all platform-specific native binaries for old Node versions (< 0.12) | ||
| * since we don't know which Node version will actually run this module. | ||
| * | ||
| * Compatible with Node.js 0.8+ | ||
| */ | ||
| #!/usr/bin/env node | ||
| var fs = require('fs'); | ||
| var path = require('path'); | ||
| var os = require('os'); | ||
| var exit = require('exit-compat'); | ||
| // Polyfills for old Node versions | ||
| var mkdirp = require('mkdirp-classic'); | ||
| // execSync doesn't exist in Node 0.8, use spawn | ||
| var spawn = require('child_process').spawn; | ||
| // Configuration | ||
| var GITHUB_REPO = 'kmalakoff/thread-sleep-compat'; | ||
| var BINARIES_VERSION = require('../package.json').binaryVersion; | ||
| // ABI versions needed for Node < 0.12 (normalized to decimal strings) | ||
| // ABI 1: Node 0.8.x and earlier | ||
| // ABI 11: Node 0.10.x | ||
| // Note: ABI 14 (Node 0.11.x) skipped - unstable dev branch, not widely used | ||
| var ABI_VERSIONS = ['v1', 'v11']; | ||
| var root = path.join(__dirname, '..'); | ||
| var pkg = require(path.join(root, 'package.json')); | ||
| /** | ||
| * Get ALL architectures for the current platform | ||
| * Old Node versions may run under emulation (Rosetta, QEMU, WoW64) | ||
| * so we download all available binaries for the platform | ||
| */ | ||
| function getArchitectures() { | ||
| var platform = os.platform(); | ||
| if (platform === 'darwin') { | ||
| return ['arm64', 'x64']; | ||
| } | ||
| if (platform === 'linux') { | ||
| return ['arm64', 'arm', 'x64']; | ||
| } | ||
| if (platform === 'win32') { | ||
| return ['ia32', 'x64']; | ||
| } | ||
| // Fallback to current arch for unknown platforms | ||
| return [os.arch()]; | ||
| var compiled = path.join(__dirname, '..', 'dist', 'cjs', 'scripts', 'postinstall.js'); | ||
| if (fs.existsSync(compiled)) { | ||
| require(compiled); | ||
| } else { | ||
| console.log('postinstall: Skipping (dist/ not built yet - run npm run build)'); | ||
| } | ||
| /** | ||
| * Get the download URL for the binary archive | ||
| */ | ||
| function getDownloadUrl(abiVersion, arch) { | ||
| var platform = os.platform(); | ||
| var filename = [pkg.name, 'node', abiVersion, platform, arch].join('-'); | ||
| var archiveName = filename + '.tar.gz'; | ||
| return { | ||
| url: 'https://github.com/' + GITHUB_REPO + '/releases/download/binaries-v' + BINARIES_VERSION + '/' + archiveName, | ||
| filename: filename, | ||
| }; | ||
| } | ||
| /** | ||
| * Get temp directory (compatible with Node 0.8) | ||
| */ | ||
| function getTmpDir() { | ||
| return typeof os.tmpdir === 'function' ? os.tmpdir() : process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp'; | ||
| } | ||
| /** | ||
| * Download using curl (macOS, Linux, Windows 10+) | ||
| */ | ||
| function downloadWithCurl(url, destPath, callback) { | ||
| var curl = spawn('curl', ['-L', '-f', '-s', '-o', destPath, url]); | ||
| curl.on('close', function (code) { | ||
| if (code !== 0) { | ||
| // curl exit codes: 22 = HTTP error (4xx/5xx), 56 = receive error (often 404 with -f) | ||
| if (code === 22 || code === 56) { | ||
| callback(new Error('HTTP 404')); | ||
| } else { | ||
| callback(new Error('curl failed with exit code ' + code)); | ||
| } | ||
| return; | ||
| } | ||
| callback(null); | ||
| }); | ||
| curl.on('error', function (err) { | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Download using PowerShell (Windows 7+ fallback) | ||
| */ | ||
| function downloadWithPowerShell(url, destPath, callback) { | ||
| var psCommand = 'Invoke-WebRequest -Uri "' + url + '" -OutFile "' + destPath + '" -UseBasicParsing'; | ||
| var ps = spawn('powershell', ['-NoProfile', '-Command', psCommand]); | ||
| ps.on('close', function (code) { | ||
| if (code !== 0) { | ||
| callback(new Error('PowerShell download failed with exit code ' + code)); | ||
| return; | ||
| } | ||
| callback(null); | ||
| }); | ||
| ps.on('error', function (err) { | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Download a file - tries curl first, falls back to PowerShell on Windows | ||
| * Node 0.8's OpenSSL doesn't support TLS 1.2+ required by GitHub | ||
| */ | ||
| function downloadFile(url, destPath, callback) { | ||
| downloadWithCurl(url, destPath, function (err) { | ||
| if (!err) { | ||
| callback(null); | ||
| return; | ||
| } | ||
| // If curl failed and we're on Windows, try PowerShell | ||
| if (os.platform() === 'win32' && err.message && err.message.indexOf('ENOENT') >= 0) { | ||
| downloadWithPowerShell(url, destPath, callback); | ||
| return; | ||
| } | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Extract tar.gz archive | ||
| * Available on: macOS, Linux, Windows 10+ | ||
| */ | ||
| function extractArchive(archivePath, destDir, callback) { | ||
| var tar = spawn('tar', ['-xzf', archivePath, '-C', destDir]); | ||
| tar.on('close', function (code) { | ||
| if (code !== 0) { | ||
| callback(new Error('tar failed with exit code ' + code)); | ||
| return; | ||
| } | ||
| callback(null); | ||
| }); | ||
| tar.on('error', function (err) { | ||
| callback(err); | ||
| }); | ||
| } | ||
| /** | ||
| * Download and extract a single binary | ||
| */ | ||
| function downloadBinary(abiVersion, arch, outDir, callback) { | ||
| var info = getDownloadUrl(abiVersion, arch); | ||
| var destDir = path.join(outDir, info.filename); | ||
| // Check if binary already exists | ||
| var bindingPath = path.join(destDir, 'build', 'Release', 'thread_sleep.node'); | ||
| if (fs.existsSync(bindingPath)) { | ||
| callback(null, 'exists'); | ||
| return; | ||
| } | ||
| var tempPath = path.join(getTmpDir(), 'thread-sleep-compat-' + abiVersion + '-' + arch + '-' + Date.now() + '.tar.gz'); | ||
| downloadFile(info.url, tempPath, function (downloadErr) { | ||
| if (downloadErr) { | ||
| // Clean up temp file if it exists | ||
| if (fs.existsSync(tempPath)) { | ||
| try { | ||
| fs.unlinkSync(tempPath); | ||
| } catch (_e) {} | ||
| } | ||
| callback(downloadErr); | ||
| return; | ||
| } | ||
| // Create destination directory before extracting | ||
| mkdirp.sync(destDir); | ||
| extractArchive(tempPath, destDir, function (extractErr) { | ||
| // Clean up temp file | ||
| if (fs.existsSync(tempPath)) { | ||
| try { | ||
| fs.unlinkSync(tempPath); | ||
| } catch (_e) {} | ||
| } | ||
| if (extractErr) { | ||
| callback(extractErr); | ||
| return; | ||
| } | ||
| callback(null, 'downloaded'); | ||
| }); | ||
| }); | ||
| } | ||
| /** | ||
| * Build list of all downloads needed (ABIs × architectures) | ||
| */ | ||
| function getDownloadList() { | ||
| var archs = getArchitectures(); | ||
| var downloads = []; | ||
| for (var i = 0; i < ABI_VERSIONS.length; i++) { | ||
| for (var j = 0; j < archs.length; j++) { | ||
| downloads.push({ abi: ABI_VERSIONS[i], arch: archs[j] }); | ||
| } | ||
| } | ||
| return downloads; | ||
| } | ||
| /** | ||
| * Download binaries sequentially (callback-based for Node 0.8 compat) | ||
| */ | ||
| function downloadAll(downloads, outDir, index, results, callback) { | ||
| if (index >= downloads.length) { | ||
| callback(null, results); | ||
| return; | ||
| } | ||
| var item = downloads[index]; | ||
| console.log('postinstall: Downloading binary for ABI ' + item.abi + ' (' + item.arch + ')...'); | ||
| downloadBinary(item.abi, item.arch, outDir, function (err, status) { | ||
| if (err) { | ||
| results.push({ abi: item.abi, arch: item.arch, error: err.message || String(err) }); | ||
| } else { | ||
| results.push({ abi: item.abi, arch: item.arch, status: status }); | ||
| } | ||
| downloadAll(downloads, outDir, index + 1, results, callback); | ||
| }); | ||
| } | ||
| /** | ||
| * Main installation function | ||
| */ | ||
| function main() { | ||
| var platform = os.platform(); | ||
| var archs = getArchitectures(); | ||
| console.log('postinstall: Installing thread-sleep-compat binaries for ' + platform + ' (' + archs.join(', ') + ')'); | ||
| var outDir = path.join(root, 'out'); | ||
| // Create output directory | ||
| mkdirp.sync(outDir); | ||
| var downloads = getDownloadList(); | ||
| downloadAll(downloads, outDir, 0, [], function (_err, results) { | ||
| var succeeded = 0; | ||
| var failed = 0; | ||
| var existed = 0; | ||
| for (var i = 0; i < results.length; i++) { | ||
| var r = results[i]; | ||
| if (r.error) { | ||
| failed++; | ||
| if (r.error.indexOf('404') >= 0) { | ||
| console.log('postinstall: Binary for ' + r.abi + '-' + r.arch + ' not available'); | ||
| } else { | ||
| console.log('postinstall: Failed to download ' + r.abi + '-' + r.arch + ': ' + r.error); | ||
| } | ||
| } else if (r.status === 'exists') { | ||
| existed++; | ||
| } else { | ||
| succeeded++; | ||
| } | ||
| } | ||
| if (succeeded > 0) { | ||
| console.log('postinstall: Downloaded ' + succeeded + ' binary(ies)'); | ||
| } | ||
| if (existed > 0) { | ||
| console.log('postinstall: ' + existed + ' binary(ies) already existed'); | ||
| } | ||
| if (failed === results.length) { | ||
| console.log(''); | ||
| console.log('postinstall: No binaries available for ' + platform); | ||
| console.log('thread-sleep-compat will work on Node >= 0.12 but not on older versions.'); | ||
| } | ||
| exit(0); | ||
| }); | ||
| } | ||
| main(); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
76591
145.19%45
18.42%824
82.3%19
58.33%3
200%