summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md12
-rw-r--r--docs/cli.md41
-rw-r--r--package-lock.json12
-rw-r--r--package.json1
-rw-r--r--src/@types/astro.ts18
-rw-r--r--src/cli.ts23
-rw-r--r--src/config.ts11
-rw-r--r--src/dev.ts2
-rw-r--r--test/config-path.test.js24
-rw-r--r--test/config-port.test.js29
-rw-r--r--test/fixtures/config-path/config/my-config.mjs5
-rw-r--r--test/fixtures/config-port/astro.config.mjs6
-rw-r--r--test/helpers.js9
13 files changed, 173 insertions, 20 deletions
diff --git a/README.md b/README.md
index 32ddd7109..92790b883 100644
--- a/README.md
+++ b/README.md
@@ -52,8 +52,16 @@ export default {
},
/** Your public domain, e.g.: https://my-site.dev/ */
site: '',
- /** Generate sitemap (set to "false" to disable) */
- sitemap: true,
+ /** Options specific to `astro build` */
+ buildOptions: {
+ /** Generate sitemap (set to "false" to disable) */
+ sitemap: true,
+ },
+ /** Options for the development server run with `astro dev`. */
+ devOptions: {
+ /** The port to run the dev server on. */
+ port: 3000
+ }
};
```
diff --git a/docs/cli.md b/docs/cli.md
new file mode 100644
index 000000000..c413323d5
--- /dev/null
+++ b/docs/cli.md
@@ -0,0 +1,41 @@
+## 👩🏽‍💻 Command Line Interface
+
+### Global Flags
+
+#### `--config path`
+
+Specify the path to the config file. Defaults to `astro.config.mjs`. Use this if you use a different name for your configuration file or have your config file in another folder.
+
+```shell
+astro --config config/astro.config.mjs dev
+```
+
+#### `--project-root path`
+
+Specify the path to the project root. If not specified the current working directory is assumed to be the root.
+
+The root is used for finding the Astro configuration file.
+
+```shell
+astro --project-root examples/snowpack dev
+```
+
+#### `--version`
+
+Print the Astro version number and exit.
+
+#### `--help`
+
+Print the help message and exit.
+
+### Commands
+
+#### `astro dev`
+
+Runs the Astro development server. This starts an HTTP server that responds to requests for pages stored in `astro/pages` (or which folder is specified in your [configuration](../README.md##%EF%B8%8F-configuration)).
+
+__Flags__
+
+##### `--port`
+
+Specifies should port to run on. Defaults to `3000`. \ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index d15448f3d..8032598e8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1788,13 +1788,6 @@
"onetime": "^5.1.2",
"signal-exit": "^3.0.3",
"strip-final-newline": "^2.0.0"
- },
- "dependencies": {
- "get-stream": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz",
- "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg=="
- }
}
},
"extend": {
@@ -2011,6 +2004,11 @@
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
},
+ "get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
+ },
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
diff --git a/package.json b/package.json
index a73e62c43..02bec1423 100644
--- a/package.json
+++ b/package.json
@@ -98,6 +98,7 @@
"eslint": "^7.22.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "^3.3.1",
+ "execa": "^5.0.0",
"prettier": "^2.2.1",
"typescript": "^4.2.3",
"uvu": "^0.5.1"
diff --git a/src/@types/astro.ts b/src/@types/astro.ts
index 4ecab847d..d991dbbcf 100644
--- a/src/@types/astro.ts
+++ b/src/@types/astro.ts
@@ -17,7 +17,23 @@ export interface AstroConfig {
/** Public URL base (e.g. 'https://mysite.com'). Used in generating sitemaps and canonical URLs. */
site?: string;
/** Generate a sitemap? */
- sitemap: boolean;
+ buildOptions: {
+ sitemap: boolean;
+ };
+ devOptions: {
+ port: number;
+ projectRoot?: string;
+ };
+}
+
+export type AstroUserConfig = Omit<AstroConfig, 'buildOptions' | 'devOptions'> & {
+ buildOptions: {
+ sitemap: boolean;
+ };
+ devOptions: {
+ port?: number;
+ projectRoot?: string;
+ };
}
export interface JsxItem {
diff --git a/src/cli.ts b/src/cli.ts
index c56a4c098..be0dfe27a 100644
--- a/src/cli.ts
+++ b/src/cli.ts
@@ -20,14 +20,20 @@ type cliCommand = 'help' | 'version' | 'dev' | 'build';
interface CLIState {
cmd: cliCommand;
options: {
+ projectRoot?: string;
sitemap?: boolean;
+ port?: number;
+ config?: string;
};
}
/** Determine which action the user requested */
function resolveArgs(flags: Arguments): CLIState {
const options: CLIState['options'] = {
+ projectRoot: typeof flags.projectRoot === 'string' ? flags.projectRoot: 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
};
if (flags.version) {
@@ -52,13 +58,15 @@ function printHelp() {
console.error(` ${colors.bold('astro')} - Futuristic web development tool.
${colors.bold('Commands:')}
- astro dev Run Astro in development mode.
- astro build Build a pre-compiled production version of your site.
+ astro dev Run Astro in development mode.
+ astro build Build a pre-compiled production version of your site.
${colors.bold('Flags:')}
- --version Show the version number and exit.
- --help Show this help message.
+ --config <path> Specify the path to the Astro config file.
+ --project-root <path> Specify the path to the project root folder.
--no-sitemap Disable sitemap generation (build only).
+ --version Show the version number and exit.
+ --help Show this help message.
`);
}
@@ -70,14 +78,17 @@ async function printVersion() {
/** Merge CLI flags & config options (CLI flags take priority) */
function mergeCLIFlags(astroConfig: AstroConfig, flags: CLIState['options']) {
- if (typeof flags.sitemap === 'boolean') astroConfig.sitemap = flags.sitemap;
+ if (typeof flags.sitemap === 'boolean') astroConfig.buildOptions.sitemap = flags.sitemap;
+ if (typeof flags.port === 'number') astroConfig.devOptions.port = flags.port;
}
/** Handle `astro run` command */
async function runCommand(rawRoot: string, cmd: (a: AstroConfig) => Promise<void>, options: CLIState['options']) {
try {
- const astroConfig = await loadConfig(rawRoot);
+ const projectRoot = options.projectRoot || rawRoot;
+ const astroConfig = await loadConfig(projectRoot, options.config);
mergeCLIFlags(astroConfig, options);
+
return cmd(astroConfig);
} catch (err) {
console.error(colors.red(err.toString() || err));
diff --git a/src/config.ts b/src/config.ts
index 937499923..af618a27f 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -24,6 +24,10 @@ function validateConfig(config: any): void {
throw new Error(`[astro config] ${key}: ${JSON.stringify(config[key])}\n Expected boolean, received ${type(config[key])}.`);
}
}
+
+ if(config.devOptions?.port !== 'number') {
+ throw new Error(`[astro config] devOptions.port: Expected number, received ${type(config.devOptions?.port)}`)
+ }
}
/** Set default config values */
@@ -34,7 +38,8 @@ function configDefaults(userConfig?: any): any {
if (!config.astroRoot) config.astroRoot = './astro';
if (!config.dist) config.dist = './_site';
if (!config.public) config.public = './public';
-
+ if (!config.devOptions) config.devOptions = {};
+ if (!config.devOptions.port) config.devOptions.port = 3000;
if (typeof config.sitemap === 'undefined') config.sitemap = true;
return config;
@@ -53,13 +58,13 @@ function normalizeConfig(userConfig: any, root: string): AstroConfig {
}
/** Attempt to load an `astro.config.mjs` file */
-export async function loadConfig(rawRoot: string | undefined): Promise<AstroConfig> {
+export async function loadConfig(rawRoot: string | undefined, configFileName = 'astro.config.mjs'): Promise<AstroConfig> {
if (typeof rawRoot === 'undefined') {
rawRoot = process.cwd();
}
const root = pathResolve(rawRoot);
- const astroConfigPath = pathJoin(root, 'astro.config.mjs');
+ const astroConfigPath = pathJoin(root, configFileName);
// load
let config: any;
diff --git a/src/dev.ts b/src/dev.ts
index 8c4140259..8f93aabf6 100644
--- a/src/dev.ts
+++ b/src/dev.ts
@@ -8,7 +8,6 @@ import { defaultLogDestination, error, parseError } from './logger.js';
import { createRuntime } from './runtime.js';
const hostname = '127.0.0.1';
-const port = 3000;
// Disable snowpack from writing to stdout/err.
snowpackLogger.level = 'silent';
@@ -65,6 +64,7 @@ export default async function dev(astroConfig: AstroConfig) {
}
});
+ const port = astroConfig.devOptions.port;
server.listen(port, hostname, () => {
// eslint-disable-next-line no-console
console.log(`Server running at http://${hostname}:${port}/`);
diff --git a/test/config-path.test.js b/test/config-path.test.js
new file mode 100644
index 000000000..a13e099b3
--- /dev/null
+++ b/test/config-path.test.js
@@ -0,0 +1,24 @@
+import { suite } from 'uvu';
+import * as assert from 'uvu/assert';
+import { runDevServer } from './helpers.js';
+
+const ConfigPath = suite('Config path');
+
+const root = new URL('./fixtures/config-path/', import.meta.url);
+ConfigPath('can be passed via --config', async (context) => {
+ const configPath = new URL('./config/my-config.mjs', root).pathname;
+ const args = ['--config', configPath];
+ const process = runDevServer(root, args);
+
+ process.stdout.setEncoding('utf8');
+ for await (const chunk of process.stdout) {
+ if(/Server running at/.test(chunk)) {
+ break;
+ }
+ }
+
+ process.kill();
+ assert.ok(true, 'Server started');
+});
+
+ConfigPath.run();
diff --git a/test/config-port.test.js b/test/config-port.test.js
new file mode 100644
index 000000000..9b5f7b14c
--- /dev/null
+++ b/test/config-port.test.js
@@ -0,0 +1,29 @@
+import { suite } from 'uvu';
+import * as assert from 'uvu/assert';
+import { runDevServer } from './helpers.js';
+import { loadConfig } from '../lib/config.js';
+
+const ConfigPort = suite('Config path');
+
+const root = new URL('./fixtures/config-port/', import.meta.url);
+ConfigPort('can be specified in the astro config', async (context) => {
+ const astroConfig = await loadConfig(root.pathname);
+ assert.equal(astroConfig.devOptions.port, 3001);
+});
+
+ConfigPort('can be specified via --port flag', async (context) => {
+ const args = ['--port', '3002'];
+ const process = runDevServer(root, args);
+
+ process.stdout.setEncoding('utf8');
+ for await (const chunk of process.stdout) {
+ if(/Server running at/.test(chunk)) {
+ assert.ok(/:3002/.test(chunk), 'Using the right port');
+ break;
+ }
+ }
+
+ process.kill();
+});
+
+ConfigPort.run();
diff --git a/test/fixtures/config-path/config/my-config.mjs b/test/fixtures/config-path/config/my-config.mjs
new file mode 100644
index 000000000..f50751cfd
--- /dev/null
+++ b/test/fixtures/config-path/config/my-config.mjs
@@ -0,0 +1,5 @@
+export default {
+ extensions: {
+ '.jsx': 'preact',
+ },
+};
diff --git a/test/fixtures/config-port/astro.config.mjs b/test/fixtures/config-port/astro.config.mjs
new file mode 100644
index 000000000..61858cdae
--- /dev/null
+++ b/test/fixtures/config-port/astro.config.mjs
@@ -0,0 +1,6 @@
+
+export default {
+ devOptions: {
+ port: 3001
+ }
+} \ No newline at end of file
diff --git a/test/helpers.js b/test/helpers.js
index 8ca42ea11..eb7cabb0b 100644
--- a/test/helpers.js
+++ b/test/helpers.js
@@ -4,6 +4,8 @@ import { readFile } from 'fs/promises';
import { createRuntime } from '../lib/runtime.js';
import { loadConfig } from '../lib/config.js';
import * as assert from 'uvu/assert';
+import execa from 'execa';
+
/** setup fixtures for tests */
export function setup(Suite, fixturePath) {
let runtime, setupError;
@@ -62,3 +64,10 @@ export function setupBuild(Suite, fixturePath) {
assert.equal(setupError, undefined);
});
}
+
+const cliURL = new URL('../astro.mjs', import.meta.url);
+export function runDevServer(root, additionalArgs = []) {
+ const args = [cliURL.pathname, 'dev', '--project-root', root.pathname].concat(additionalArgs);
+ const proc = execa('node', args);
+ return proc;
+} \ No newline at end of file