Files
Andrei 58f8093689 Rebrand from 'Redirect Intelligence v2' to 'URL Tracker Tool V2' throughout UI
- Updated all component headers and documentation
- Changed navbar and footer branding
- Updated homepage hero badge
- Modified page title in index.html
- Simplified footer text to 'Built with ❤️'
- Consistent V2 capitalization across all references
2025-08-19 19:12:23 +00:00

275 lines
10 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* We need to run a platform-specific `turbo`. The dependency _should_
* have already been installed, but it's possible that it has not.
*/
const child_process = require('child_process');
const fs = require('fs');
const path = require('path');
// If we do not find the correct platform binary, should we attempt to install it?
const SHOULD_INSTALL = true;
// If we do not find the correct platform binary, should we trust calling an emulated variant?
const SHOULD_ATTEMPT_EMULATED = true;
// Relies on the fact that each tarball publishes the `package.json`.
// We can simply cd into the `turbo` directory and install there.
function installUsingNPM() {
const turboPath = path.dirname(require.resolve('turbo/package'));
// Erase "npm_config_global" so that "npm install --global turbo" works.
// Otherwise this nested "npm install" will also be global, and the install
// will deadlock waiting for the global installation lock.
const env = { ...process.env, npm_config_global: undefined };
child_process.execSync(
`npm install --loglevel=error --prefer-offline --no-audit --progress=false`,
{ cwd: turboPath, stdio: "pipe", env }
);
}
// npm has multiple places that we need to look for a package name.
function hasPackage(sourceObject, packageName) {
return !!sourceObject[packageName] || !!sourceObject[`node_modules/${packageName}`];
}
// This provides logging messages as it progresses towards calculating the binary path.
function getBinaryPath() {
// First we see if the user has configured a particular binary path.
const TURBO_BINARY_PATH = process.env.TURBO_BINARY_PATH;
if (TURBO_BINARY_PATH) {
if (!fs.existsSync(TURBO_BINARY_PATH)) {
console.error(`Turborepo was unable to find the executable specified by TURBO_BINARY_PATH:\n${TURBO_BINARY_PATH}`);
console.error();
console.error(`TURBO_BINARY_PATH is intended for development use-cases. You likely want to unset the environment variable.`);
process.exit(1);
} else {
return TURBO_BINARY_PATH;
}
}
const availablePlatforms = [
'darwin',
'linux',
'windows',
];
const availableArchs = [
'64',
'arm64',
];
// We need to figure out which binary to hand the user.
// The only place where the binary can be at this point is `require.resolve`-able
// relative to this package as it should be installed as an optional dependency.
let { platform, arch } = process;
// Node uses `win32` but we want to use `windows` for consistency with
// our package naming conventions (i.e. `turbo-windows-64`).
if (platform === "win32") {
platform = "windows";
}
const resolvedArch = arch === 'x64' ? '64' : arch;
const ext = platform === 'windows' ? '.exe' : '';
// Try all places in order until we get a hit.
// 1. The package which contains the binary we _should_ be running.
const correctBinary = availablePlatforms.includes(platform) && availableArchs.includes(resolvedArch) ? `turbo-${platform}-${resolvedArch}/bin/turbo${ext}` : null;
if (correctBinary !== null) {
try {
return require.resolve(`${correctBinary}`);
} catch (e) {}
}
// 2. Install the binary that they need just in time.
if (SHOULD_INSTALL && correctBinary !== null) {
console.warn('Turborepo did not find the correct binary for your platform.');
console.warn('We will attempt to install it now.');
try {
installUsingNPM();
const resolvedPath = require.resolve(`${correctBinary}`);
console.warn('Installation has succeeded.');
return resolvedPath;
} catch (e) {
console.warn('Installation has failed.');
}
}
// 3. Both Windows and macOS ARM boxes can run x64 binaries. Attempt to run under emulation.
const alternateBinary = (arch === "arm64" && ['darwin', 'windows'].includes(platform)) ? `turbo-${platform}-64/bin/turbo${ext}` : null;
if (SHOULD_ATTEMPT_EMULATED && alternateBinary !== null) {
try {
const resolvedPath = require.resolve(`${alternateBinary}`);
console.warn(`Turborepo detected that you're running:\n${platform} ${resolvedArch}.`);
console.warn(`We were not able to find the binary at:\n${correctBinary}`);
console.warn(`We found a possibly-compatible binary at:\n${alternateBinary}`);
console.warn(`We will attempt to run that binary.`);
return resolvedPath;
} catch (e) {}
}
// We are not going to run `turbo` this invocation.
// Let's give the best error message that we can.
// Possible error scenarios:
// - The user is on a platform/arch combination we do not support.
// - We somehow got detection wrong and never attempted to run the _actual_ `correctBinary` or `alternateBinary`.
// - The user doesn't have the correct packages installed for their platform.
// Explain our detection attempt:
console.error();
console.error('***');
console.error();
console.error(`Turborepo failed to start.`);
console.error();
console.error(`Turborepo detected that you are running:\n${platform} ${resolvedArch}`);
// Tell them if we support their platform at all.
if (!availablePlatforms.includes(platform)) {
console.error();
console.error('Turborepo does not presently support your platform.');
process.exit(1);
} else if (!availableArchs.includes(resolvedArch)) {
if (availablePlatforms.includes(platform)) {
console.error();
console.error('Turborepo supports your platform, but does not support your processor architecture.');
process.exit(1);
} else {
console.error();
console.error('Turborepo does not either of your platform or processor architecture.');
process.exit(1);
}
}
if (correctBinary !== null) {
console.error();
console.error('***');
console.error();
console.error(`We were not able to find the binary at:\n${correctBinary}`);
console.error();
console.error(`We looked for it at:`);
console.error(require.resolve.paths(correctBinary).join('\n'));
}
if (alternateBinary !== null) {
console.error();
console.error('***');
console.error();
console.error(`Your platform (${platform}) can sometimes run x86 under emulation.`);
console.error(`We did not find a possibly-compatible binary at:\n${alternateBinary}`);
console.error();
console.error(`We looked for it at:`);
console.error(require.resolve.paths(alternateBinary).join('\n'));
}
// Investigate other failure modes.
// Has the wrong platform's binaries available.
const availableBinaries = availablePlatforms.map(platform => availableArchs.map(arch => `turbo-${platform}-${arch}/bin/turbo${platform === 'windows' ? '.exe' : ''}`)).flat();
const definitelyWrongBinaries = availableBinaries.filter(binary => binary !== correctBinary || binary !== correctBinary);;
const otherInstalled = definitelyWrongBinaries.filter(binaryPath => {
try {
return require.resolve(binaryPath);
} catch (e) {}
});
console.error();
console.error('***');
console.error();
if (otherInstalled.length > 0) {
console.error('Turborepo checked to see if binaries for another platform are installed.');
console.error('This typically indicates an error in sharing of pre-resolved node_modules across platforms.');
console.error('One common reason for this is copying files to Docker.');
console.error();
console.error(`We found these unnecessary binaries:`);
console.error(otherInstalled.join('\n'));
} else {
console.error(`We did not find any binaries on this system.`);
console.error(`This can happen if you run installation with the --no-optional flag.`);
}
// Check to see if we have partially-populated dependencies in the npm lockfile.
const MAX_LOOKUPS = 10;
const availablePackages = availablePlatforms.map(platform => availableArchs.map(arch => `turbo-${platform}-${arch}`)).flat();
try {
// Attempt to find project root.
const selfPath = require.resolve('turbo/package');
let previous = null;
let current = path.join(selfPath, '..', '..', 'package-lock.json');
for (let i = 0; previous !== current && i < MAX_LOOKUPS; i++) {
try {
const lockfile = fs.readFileSync(current);
const parsedLockfile = JSON.parse(lockfile);
const sourceObject = parsedLockfile?.dependencies ?? parsedLockfile?.packages ?? {};
// If we don't show up in the lockfile it's the wrong lockfile.
if (hasPackage(sourceObject, 'turbo')) {
// Check to see if all of `turbo-<PLATFORM>-<ARCH>` is included.
const hasAllPackages = availablePackages.every(package => hasPackage(sourceObject, package));
if (!hasAllPackages) {
console.error();
console.error('***');
console.error();
console.error(`Turborepo detected that your lockfile (${current}) does not enumerate all available platforms.`);
console.error('This is likely a consequence of an npm issue: https://github.com/npm/cli/issues/4828.');
// Let's build their repair command:
let version = '';
let environment = '';
if (parsedLockfile?.packages[""]?.dependencies?.turbo) {
version = `@${parsedLockfile.packages[""].dependencies.turbo}`;
environment = ' --save-prod';
} else if (parsedLockfile?.packages[""]?.devDependencies?.turbo) {
version = `@${parsedLockfile.packages[""].devDependencies.turbo}`;
environment = ' --save-dev';
} else if (parsedLockfile?.packages[""]?.optionalDependencies?.turbo) {
version = `@${parsedLockfile.packages[""].optionalDependencies.turbo}`;
environment = ' --save-optional';
}
console.error();
console.error('To resolve this issue for your repository, run:');
console.error(`npm install turbo${version} --package-lock-only${environment} && npm install`);
console.error();
console.error(`You will need to commit the updated lockfile.`);
}
break;
}
break;
} catch (e) {}
let next = path.join(current, '..', '..', 'package-lock.json');
previous = current;
current = next;
}
} catch (e) {}
console.error();
console.error('***');
console.error();
console.error(`If you believe this is an error, please include this message in your report.`);
process.exit(1);
}
// Run the binary we got.
try {
child_process.execFileSync(
getBinaryPath(),
process.argv.slice(2),
{ stdio: "inherit" }
);
} catch (e) {
if (e && e.status) process.exit(e.status);
throw e;
}