diff --git a/.changeset/fluffy-toes-jump.md b/.changeset/fluffy-toes-jump.md new file mode 100644 index 000000000..daa1737d2 --- /dev/null +++ b/.changeset/fluffy-toes-jump.md @@ -0,0 +1,6 @@ +--- +'myst-cli': patch +'mystmd': patch +--- + +Specify port numbers for app and server ports diff --git a/packages/myst-cli/src/build/site/prepare.ts b/packages/myst-cli/src/build/site/prepare.ts index 80d1bc9dc..59ab4a508 100644 --- a/packages/myst-cli/src/build/site/prepare.ts +++ b/packages/myst-cli/src/build/site/prepare.ts @@ -11,6 +11,8 @@ export type Options = { headless?: boolean; checkLinks?: boolean; yes?: boolean; + port?: number; + serverPort?: number; writeToc?: boolean; keepHost?: boolean; extraLinkTransformers?: LinkTransformer[]; diff --git a/packages/myst-cli/src/build/site/start.ts b/packages/myst-cli/src/build/site/start.ts index caee5720e..144b432eb 100644 --- a/packages/myst-cli/src/build/site/start.ts +++ b/packages/myst-cli/src/build/site/start.ts @@ -21,8 +21,8 @@ const DEFAULT_START_COMMAND = 'npm run start'; /** * Creates a content server and a websocket that can reload and log messages to the client. */ -export async function startContentServer(session: ISession) { - const port = await getPort({ port: portNumbers(3100, 3200) }); +export async function startContentServer(session: ISession, opts?: { serverPort?: number }) { + const port = opts?.serverPort ?? (await getPort({ port: portNumbers(3100, 3200) })); const app = express(); app.use(cors()); app.get('/', (req, res) => { @@ -111,7 +111,7 @@ export async function startServer( const mystTemplate = await getMystTemplate(session, opts); if (!opts.headless) await installSiteTemplate(session, mystTemplate); await buildSite(session, opts); - const server = await startContentServer(session); + const server = await startContentServer(session, opts); const { extraLinkTransformers, extraTransforms, defaultTemplate } = opts; if (!opts.buildStatic) { watchContent(session, server.reload, { @@ -130,10 +130,8 @@ export async function startServer( session.log.info( `\n\n\t✨✨✨ Starting ${mystTemplate.getValidatedTemplateYml().title} ✨✨✨\n\n`, ); - const port = await getPort({ port: portNumbers(3000, 3100) }); - const appServer = { - port, - } as AppServer; + const port = opts?.port ?? (await getPort({ port: portNumbers(3000, 3100) })); + const appServer = { port } as AppServer; await new Promise((resolve) => { const start = makeExecutable( mystTemplate.getValidatedTemplateYml().build?.start ?? DEFAULT_START_COMMAND, diff --git a/packages/mystmd/src/options.ts b/packages/mystmd/src/options.ts index bd3db0379..13ef7d146 100644 --- a/packages/mystmd/src/options.ts +++ b/packages/mystmd/src/options.ts @@ -1,4 +1,10 @@ -import { Option } from 'commander'; +import { InvalidArgumentError, Option } from 'commander'; + +function parseInt(value: any) { + const parsedValue = Number.parseInt(value, 10); + if (isNaN(parsedValue)) throw new InvalidArgumentError('Not a number.'); + return parsedValue; +} export function makePdfOption(description: string) { return new Option('--pdf', description).default(false); @@ -94,6 +100,23 @@ export function makeHeadlessOption() { ).default(false); } +export function makePortOption() { + return new Option('--port ', 'Run the application server from the specified port number') + .argParser(parseInt) + .env('PORT') + .default(undefined); +} + +export function makeServerPortOption() { + return new Option( + '--server-port ', + 'Run the content server from the specified port number', + ) + .argParser(parseInt) + .env('SERVER_PORT') + .default(undefined); +} + export function makeYesOption() { return new Option('-y, --yes', 'Automatically respond yes to prompts').default(false); } diff --git a/packages/mystmd/src/site.ts b/packages/mystmd/src/site.ts index ae304b16c..af8746f51 100644 --- a/packages/mystmd/src/site.ts +++ b/packages/mystmd/src/site.ts @@ -1,13 +1,20 @@ import { Command } from 'commander'; import { Session, startServer } from 'myst-cli'; import { clirun } from './clirun.js'; -import { makeKeepHostOption, makeHeadlessOption } from './options.js'; +import { + makeKeepHostOption, + makeHeadlessOption, + makePortOption, + makeServerPortOption, +} from './options.js'; export function makeStartCLI(program: Command) { const command = new Command('start') .description('Start the current project as a website') .addOption(makeKeepHostOption()) .addOption(makeHeadlessOption()) + .addOption(makePortOption()) + .addOption(makeServerPortOption()) .action(clirun(Session, startServer, program)); return command; }