UNPKG

@shopify/plugin-cloudflare

Version:

Enables the creation of Cloudflare tunnels from `shopify app dev`, allowing previews from any device

128 lines 5.35 kB
/* eslint-disable @typescript-eslint/no-non-null-assertion */ // Install script for cloudflared, derived from https://github.com/JacobLinCool/node-cloudflared import { basename, dirname, joinPath } from '@shopify/cli-kit/node/path'; import { outputDebug } from '@shopify/cli-kit/node/output'; import { fetch } from '@shopify/cli-kit/node/http'; import { chmod, fileExistsSync, mkdirSync, renameFile, unlinkFileSync, createFileWriteStream, } from '@shopify/cli-kit/node/fs'; import { fileURLToPath } from 'url'; import util from 'util'; import { pipeline } from 'stream'; // eslint-disable-next-line no-restricted-imports import { execSync, execFileSync } from 'child_process'; export const CURRENT_CLOUDFLARE_VERSION = '2024.8.2'; const CLOUDFLARE_REPO = `https://github.com/cloudflare/cloudflared/releases/download/${CURRENT_CLOUDFLARE_VERSION}/`; const LINUX_URL = { arm64: 'cloudflared-linux-arm64', arm: 'cloudflared-linux-arm', x64: 'cloudflared-linux-amd64', ia32: 'cloudflared-linux-386', }; const MACOS_URL = { arm64: 'cloudflared-darwin-arm64.tgz', x64: 'cloudflared-darwin-amd64.tgz', }; const WINDOWS_URL = { x64: 'cloudflared-windows-amd64.exe', ia32: 'cloudflared-windows-386.exe', arm64: 'cloudflared-windows-amd64.exe', }; const URL = { linux: LINUX_URL, darwin: MACOS_URL, win32: WINDOWS_URL, }; function getURL(platform = process.platform, arch = process.arch) { const keys = Object.keys(URL); if (!keys.includes(platform)) throw new Error(`Unsupported system platform: ${platform}`); const fileName = URL[platform][arch]; if (fileName === undefined) { throw new Error(`Unsupported system arch: ${arch}`); } return CLOUDFLARE_REPO + fileName; } /** * Get the path where the binary should be installed. * If the environment variable SHOPIFY_CLI_CLOUDFLARED_PATH is set, use that. */ function getBinPathTarget(env = process.env, platform = process.platform) { if (env.SHOPIFY_CLI_CLOUDFLARED_PATH) { return env.SHOPIFY_CLI_CLOUDFLARED_PATH; } return joinPath(dirname(fileURLToPath(import.meta.url)), '..', 'bin', platform === 'win32' ? 'cloudflared.exe' : 'cloudflared'); } export default async function install(env = process.env, platform = process.platform, arch = process.arch) { if (env.SHOPIFY_CLI_IGNORE_CLOUDFLARED) { outputDebug('Skipping cloudflared installation because SHOPIFY_CLI_IGNORE_CLOUDFLARED is set'); return; } const fileUrlPath = getURL(platform, arch); const binTarget = getBinPathTarget(env, platform); if (fileExistsSync(binTarget)) { // --version returns an string like "cloudflared version 2023.3.1 (built 2023-03-13-1444 UTC)" try { const versionArray = execFileSync(binTarget, ['--version'], { encoding: 'utf8' }).split(' '); const versionNumber = versionArray.length > 2 ? versionArray[2] : '0.0.0'; const needsUpdate = versionIsGreaterThan(CURRENT_CLOUDFLARE_VERSION, versionNumber); if (!needsUpdate) { outputDebug('cloudflared already installed, skipping'); return; } // eslint-disable-next-line no-catch-all/no-catch-all } catch { outputDebug('version check failed, reinstalling'); } } if (platform === 'linux') { await installLinux(fileUrlPath, binTarget); } else if (platform === 'darwin') { await installMacos(fileUrlPath, binTarget); } else if (platform === 'win32') { await installWindows(fileUrlPath, binTarget); } else { throw new Error(`Unsupported platform: ${platform}`); } } export function versionIsGreaterThan(versionA, versionB) { const [majorA, minorA, patchA] = versionA.split('.').map(Number); const [majorB, minorB, patchB] = versionB.split('.').map(Number); // Compare major versions if (majorA !== majorB) return (majorA ?? 0) > (majorB ?? 0); // If major versions are equal, compare minor versions if (minorA !== minorB) return (minorA ?? 0) > (minorB ?? 0); // If minor versions are also equal, compare patch versions return (patchA ?? 0) > (patchB ?? 0); } async function installLinux(file, binTarget) { await downloadFile(file, binTarget); await chmod(binTarget, '755'); } async function installWindows(file, binTarget) { await downloadFile(file, binTarget); } async function installMacos(file, binTarget) { await downloadFile(file, `${binTarget}.tgz`); const filename = basename(`${binTarget}.tgz`); execSync(`tar -xzf ${filename}`, { cwd: dirname(binTarget) }); unlinkFileSync(`${binTarget}.tgz`); await renameFile(`${dirname(binTarget)}/cloudflared`, binTarget); } async function downloadFile(url, to) { if (!fileExistsSync(dirname(to))) { mkdirSync(dirname(to)); } const streamPipeline = util.promisify(pipeline); const response = await fetch(url, { redirect: 'follow' }, 'slow-request'); if (!response.ok || !response.body) throw new Error(`Couldn't download file ${url} (${response.status} ${response.statusText})`); const fileObject = createFileWriteStream(to); await streamPipeline(response.body, fileObject); return to; } //# sourceMappingURL=install-cloudflared.js.map