-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(v2): isolates feature and credits cra
- Loading branch information
1 parent
01c54c9
commit dbf356c
Showing
5 changed files
with
138 additions
and
137 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
/** | ||
* This feature was heavily inspired by create-react-app and | ||
* uses many of the same utility functions to implement it. | ||
*/ | ||
|
||
import {execSync} from 'child_process'; | ||
import detect from 'detect-port'; | ||
import isRoot from 'is-root'; | ||
import chalk from 'chalk'; | ||
import inquirer from 'inquirer'; | ||
|
||
const isInteractive = process.stdout.isTTY; | ||
|
||
const execOptions: object = { | ||
encoding: 'utf8', | ||
stdio: [ | ||
'pipe', // stdin (default) | ||
'pipe', // stdout (default) | ||
'ignore', // stderr | ||
], | ||
}; | ||
|
||
// Clears console | ||
function clearConsole(): void { | ||
process.stdout.write( | ||
process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H', | ||
); | ||
} | ||
|
||
// Gets process id of what is on port | ||
function getProcessIdOnPort(port: number): string { | ||
return execSync(`lsof -i:${port} -P -t -sTCP:LISTEN`, execOptions) | ||
.toString() | ||
.split('\n')[0] | ||
.trim(); | ||
} | ||
|
||
// Gets process command | ||
function getProcessCommand(processId: string): Promise<string | null> | string { | ||
let command: Buffer | string = execSync( | ||
`ps -o command -p ${processId} | sed -n 2p`, | ||
execOptions, | ||
); | ||
|
||
command = command.toString().replace(/\n$/, ''); | ||
|
||
return command; | ||
} | ||
|
||
// Gets directory of a process from its process id | ||
function getDirectoryOfProcessById(processId: string): string { | ||
return execSync( | ||
`lsof -p ${processId} | awk '$4=="cwd" {for (i=9; i<=NF; i++) printf "%s ", $i}'`, | ||
execOptions, | ||
) | ||
.toString() | ||
.trim(); | ||
} | ||
|
||
// Gets process on port | ||
function getProcessForPort(port: number): string | null { | ||
try { | ||
const processId = getProcessIdOnPort(port); | ||
const directory = getDirectoryOfProcessById(processId); | ||
const command = getProcessCommand(processId); | ||
return ( | ||
chalk.cyan(command) + | ||
chalk.grey(` (pid ${processId})\n`) + | ||
chalk.blue(' in ') + | ||
chalk.cyan(directory) | ||
); | ||
} catch (e) { | ||
return null; | ||
} | ||
} | ||
|
||
/** | ||
* Detects if program is running on port and prompts user | ||
* to choose another if port is already being used | ||
*/ | ||
export default async function choosePort( | ||
host: string, | ||
defaultPort: number, | ||
): Promise<number | null> { | ||
return detect(defaultPort, host).then( | ||
(port) => | ||
new Promise((resolve) => { | ||
if (port === defaultPort) { | ||
return resolve(port); | ||
} | ||
const message = | ||
process.platform !== 'win32' && defaultPort < 1024 && !isRoot() | ||
? `Admin permissions are required to run a server on a port below 1024.` | ||
: `Something is already running on port ${defaultPort}.`; | ||
if (isInteractive) { | ||
clearConsole(); | ||
const existingProcess = getProcessForPort(defaultPort); | ||
const question: any = { | ||
type: 'confirm', | ||
name: 'shouldChangePort', | ||
message: `${chalk.yellow( | ||
`${message}${ | ||
existingProcess ? ` Probably:\n ${existingProcess}` : '' | ||
}`, | ||
)}\n\nWould you like to run the app on another port instead?`, | ||
default: true, | ||
}; | ||
inquirer.prompt(question).then((answer: any) => { | ||
if (answer.shouldChangePort) { | ||
resolve(port); | ||
} else { | ||
resolve(null); | ||
} | ||
}); | ||
} else { | ||
console.log(chalk.red(message)); | ||
resolve(null); | ||
} | ||
return null; | ||
}), | ||
(err) => { | ||
throw new Error( | ||
`${chalk.red(`Could not find an open port at ${chalk.bold(host)}.`)}\n${ | ||
`Network error message: ${err.message}` || err | ||
}\n`, | ||
); | ||
}, | ||
); | ||
} |
This file contains 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
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains 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