diff --git a/.changeset/few-carpets-sing.md b/.changeset/few-carpets-sing.md new file mode 100644 index 000000000..3b938a3b2 --- /dev/null +++ b/.changeset/few-carpets-sing.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Allow dev server port to be set by `PORT` environment variable diff --git a/packages/astro/src/cli.ts b/packages/astro/src/cli.ts index accdb7978..74d1e4302 100644 --- a/packages/astro/src/cli.ts +++ b/packages/astro/src/cli.ts @@ -35,14 +35,44 @@ interface CLIState { }; } +type TypeOf = 'string' | 'boolean' | 'number'; +// Validates property types of object +const validateOptions = (opts: Record, specs: Record unknown, TypeOf]>) => + Object.entries(specs).reduce>((options, [k, spec]) => { + const v = opts[k]; + + if (typeof spec === 'string' && typeof v === spec) { + options[k] = v; + } else if (Array.isArray(spec)) { + const [coercion, test] = spec; + const result = coercion(v); + if (typeof result === test) { + options[k] = result; + } + } + + return options; + }, {}); + /** Determine which action the user requested */ function resolveArgs(flags: Arguments): CLIState { - const options: CLIState['options'] = { - projectRoot: typeof flags.projectRoot === 'string' ? flags.projectRoot : undefined, - site: typeof flags.site === 'string' ? flags.site : undefined, - sitemap: typeof flags.sitemap === 'boolean' ? flags.sitemap : undefined, - port: typeof flags.port === 'number' ? flags.port : undefined, - config: typeof flags.config === 'string' ? flags.config : undefined, + const { PORT } = process.env; + + // Merge options (Flags take priority) + const options = { + ...validateOptions( + { port: PORT }, + { + port: [parseInt, 'number'], + } + ), + ...validateOptions(flags, { + projectRoot: 'string', + site: 'string', + sitemap: 'boolean', + port: 'number', + config: 'string', + }), }; if (flags.version) { @@ -101,7 +131,7 @@ function mergeCLIFlags(astroConfig: AstroConfig, flags: CLIState['options']) { } /** Handle `astro run` command */ -async function runCommand(rawRoot: string, cmd: (a: AstroConfig, options: any) => Promise, options: CLIState['options']) { +async function runCommand(rawRoot: string, cmd: (a: AstroConfig, opts: any) => Promise, options: CLIState['options']) { try { const projectRoot = options.projectRoot || rawRoot; const astroConfig = await loadConfig(projectRoot, options.config);