diff options
author | 2021-04-05 15:56:46 -0600 | |
---|---|---|
committer | 2021-04-05 15:56:46 -0600 | |
commit | 1acd5ee310040d654f6d457a1dd53b9cb19f1f51 (patch) | |
tree | 86d46a87817d70f7b7c7aa18ce9e30a98a27ee98 /src | |
parent | 71e5de76f136a0ef76253c05bb8072898bcf08f7 (diff) | |
download | astro-1acd5ee310040d654f6d457a1dd53b9cb19f1f51.tar.gz astro-1acd5ee310040d654f6d457a1dd53b9cb19f1f51.tar.zst astro-1acd5ee310040d654f6d457a1dd53b9cb19f1f51.zip |
Allow no config (#61)
* Allow no config
* Update README
Diffstat (limited to 'src')
-rw-r--r-- | src/cli.ts | 11 | ||||
-rw-r--r-- | src/config.ts | 63 |
2 files changed, 59 insertions, 15 deletions
diff --git a/src/cli.ts b/src/cli.ts index e0f0c0dc3..71c9691d7 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -58,14 +58,13 @@ async function printVersion() { /** Handle `astro run` command */ async function runCommand(rawRoot: string, cmd: (a: AstroConfig) => Promise<void>) { - const astroConfig = await loadConfig(rawRoot); - if (typeof astroConfig === 'undefined') { - console.error(colors.red(' An astro.config.mjs file is required.\n')); - printHelp(); + try { + const astroConfig = await loadConfig(rawRoot); + return cmd(astroConfig); + } catch (err) { + console.error(colors.red(err.toString() || err)); process.exit(1); } - - return cmd(astroConfig); } const cmdMap = new Map([ diff --git a/src/config.ts b/src/config.ts index 72583df5a..fe4549929 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,25 +2,70 @@ import type { AstroConfig } from './@types/astro'; import { join as pathJoin, resolve as pathResolve } from 'path'; import { existsSync } from 'fs'; +/** Type util */ +const type = (thing: any): string => (Array.isArray(thing) ? 'Array' : typeof thing); + +/** Throws error if a user provided an invalid config. Manually-implemented to avoid a heavy validation library. */ +function validateConfig(config: any): void { + // basic + if (config === undefined || config === null) throw new Error(`[astro config] Config empty!`); + if (typeof config !== 'object') throw new Error(`[astro config] Expected object, received ${typeof config}`); + + // strings + for (const key of ['projectRoot', 'astroRoot', 'dist', 'public']) { + if (config[key] && typeof config[key] !== 'string') { + throw new Error(`[astro config] ${key}: ${JSON.stringify(config[key])}\n Expected string, received ${type(config[key])}.`); + } + } +} + +/** Set default config values */ +function configDefaults(userConfig?: any): any { + const config: any = { ...(userConfig || {}) }; + + if (!config.projectRoot) config.projectRoot = '.'; + if (!config.astroRoot) config.astroRoot = './astro'; + if (!config.dist) config.dist = './_site'; + if (!config.public) config.public = './public'; + + return config; +} + +/** Turn raw config values into normalized values */ +function normalizeConfig(userConfig: any, root: string): AstroConfig { + const config: any = { ...(userConfig || {}) }; + + config.projectRoot = new URL(config.projectRoot + '/', root); + config.astroRoot = new URL(config.astroRoot + '/', root); + config.public = new URL(config.public + '/', root); + + return config as AstroConfig; +} + /** Attempt to load an `astro.config.mjs` file */ -export async function loadConfig(rawRoot: string | undefined): Promise<AstroConfig | undefined> { +export async function loadConfig(rawRoot: string | undefined): Promise<AstroConfig> { if (typeof rawRoot === 'undefined') { rawRoot = process.cwd(); } + let config: any; + const root = pathResolve(rawRoot); const fileProtocolRoot = `file://${root}/`; const astroConfigPath = pathJoin(root, 'astro.config.mjs'); - if (!existsSync(astroConfigPath)) { - return undefined; + // load + if (existsSync(astroConfigPath)) { + config = configDefaults((await import(astroConfigPath)).default); + } else { + config = configDefaults(); } - const astroConfig: AstroConfig = (await import(astroConfigPath)).default; - astroConfig.projectRoot = new URL(astroConfig.projectRoot + '/', fileProtocolRoot); - astroConfig.astroRoot = new URL(astroConfig.astroRoot + '/', fileProtocolRoot); + // validate + validateConfig(config); + + // normalize + config = normalizeConfig(config, fileProtocolRoot); - const publicFolder = astroConfig.public ? astroConfig.public + '/' : './public/'; - astroConfig.public = new URL(publicFolder, fileProtocolRoot); - return astroConfig; + return config as AstroConfig; } |