diff options
Diffstat (limited to 'packages/astro/src/dev.ts')
-rw-r--r-- | packages/astro/src/dev.ts | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/packages/astro/src/dev.ts b/packages/astro/src/dev.ts new file mode 100644 index 000000000..4ca8e28e9 --- /dev/null +++ b/packages/astro/src/dev.ts @@ -0,0 +1,97 @@ +import type { AstroConfig } from './@types/astro'; +import type { LogOptions } from './logger.js'; + +import { logger as snowpackLogger } from 'snowpack'; +import { bold, green } from 'kleur/colors'; +import http from 'http'; +import { relative as pathRelative } from 'path'; +import { performance } from 'perf_hooks'; +import { defaultLogDestination, error, info, parseError } from './logger.js'; +import { createRuntime } from './runtime.js'; + +const hostname = '127.0.0.1'; + +// Disable snowpack from writing to stdout/err. +snowpackLogger.level = 'silent'; + +const logging: LogOptions = { + level: 'debug', + dest: defaultLogDestination, +}; + +/** The primary dev action */ +export default async function dev(astroConfig: AstroConfig) { + const startServerTime = performance.now(); + const { projectRoot } = astroConfig; + + const runtime = await createRuntime(astroConfig, { mode: 'development', logging }); + + const server = http.createServer(async (req, res) => { + const result = await runtime.load(req.url); + + switch (result.statusCode) { + case 200: { + if (result.contentType) { + res.setHeader('Content-Type', result.contentType); + } + res.statusCode = 200; + res.write(result.contents); + res.end(); + break; + } + case 404: { + const fullurl = new URL(req.url || '/', 'https://example.org/'); + const reqPath = decodeURI(fullurl.pathname); + error(logging, 'static', 'Not found', reqPath); + res.statusCode = 404; + + const fourOhFourResult = await runtime.load('/404'); + if (fourOhFourResult.statusCode === 200) { + if (fourOhFourResult.contentType) { + res.setHeader('Content-Type', fourOhFourResult.contentType); + } + res.write(fourOhFourResult.contents); + } else { + res.setHeader('Content-Type', 'text/plain'); + res.write('Not Found'); + } + res.end(); + break; + } + case 500: { + switch (result.type) { + case 'parse-error': { + const err = result.error; + err.filename = pathRelative(projectRoot.pathname, err.filename); + parseError(logging, err); + break; + } + default: { + error(logging, 'executing astro', result.error); + break; + } + } + res.statusCode = 500; + + let errorResult = await runtime.load(`/500?error=${encodeURIComponent(result.error.stack || result.error.toString())}`); + if(errorResult.statusCode === 200) { + if (errorResult.contentType) { + res.setHeader('Content-Type', errorResult.contentType); + } + res.write(errorResult.contents); + } else { + res.write(result.error.toString()); + } + res.end(); + break; + } + } + }); + + const port = astroConfig.devOptions.port; + server.listen(port, hostname, () => { + const endServerTime = performance.now(); + info(logging, 'dev server', green(`Server started in ${Math.floor(endServerTime - startServerTime)}ms.`)); + info(logging, 'dev server', `${green('Local:')} http://${hostname}:${port}/`); + }); +} |