Skip to content

Commit

Permalink
fix(v2): isolates feature and credits cra
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorallen0913 committed Jun 30, 2020
1 parent 01c54c9 commit dbf356c
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 137 deletions.
136 changes: 136 additions & 0 deletions packages/docusaurus/src/choosePort.ts
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`,
);
},
);
}
3 changes: 2 additions & 1 deletion packages/docusaurus/src/commands/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import {load} from '../server';
import {StartCLIOptions} from '@docusaurus/types';
import {CONFIG_FILE_NAME, STATIC_DIR_NAME, DEFAULT_PORT} from '../constants';
import createClientConfig from '../webpack/client';
import {applyConfigureWebpack, choosePort} from '../webpack/utils';
import {applyConfigureWebpack} from '../webpack/utils';
import choosePort from '../choosePort';

function getHost(reqHost: string | undefined): string {
return reqHost || 'localhost';
Expand Down
13 changes: 0 additions & 13 deletions packages/docusaurus/src/webpack/clearConsole.ts

This file was deleted.

65 changes: 0 additions & 65 deletions packages/docusaurus/src/webpack/getProcessForPort.ts

This file was deleted.

58 changes: 0 additions & 58 deletions packages/docusaurus/src/webpack/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,9 @@ import merge from 'webpack-merge';
import {Configuration, Loader} from 'webpack';
import {TransformOptions} from '@babel/core';
import {ConfigureWebpackUtils} from '@docusaurus/types';
import detect from 'detect-port';
import isRoot from 'is-root';
import chalk from 'chalk';
import inquirer from 'inquirer';
import clearConsole from './clearConsole';
import getProcessForPort from './getProcessForPort';

import {version as cacheLoaderVersion} from 'cache-loader/package.json';

const isInteractive = process.stdout.isTTY;

// Utility method to get style loaders
export function getStyleLoaders(
isServer: boolean,
Expand Down Expand Up @@ -156,53 +148,3 @@ export function applyConfigureWebpack(
}
return config;
}

export 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`,
);
},
);
}

0 comments on commit dbf356c

Please sign in to comment.