summaryrefslogtreecommitdiff
path: root/src/dev.ts
blob: 851379d7b9be7cb18e3e62885f4c4d68bd4e053a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import type { AstroConfig } from './@types/astro';
import type { LogOptions } from './logger.js';

import { logger as snowpackLogger } from 'snowpack';
import http from 'http';
import { relative as pathRelative } from 'path';
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';

const logging: LogOptions = {
  level: 'debug',
  dest: defaultLogDestination,
};

/** The primary dev action */
export default async function dev(astroConfig: AstroConfig) {
  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.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;
        res.setHeader('Content-Type', 'text/plain');
        res.end('Not Found');
        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;
        res.end(formatErrorForBrowser(result.error));
        break;
      }
    }
  });

  server.listen(port, hostname, () => {
    console.log(`Server running at http://${hostname}:${port}/`);
  });
}

/** Format error message */
function formatErrorForBrowser(err: Error) {
  // TODO make this pretty.
  return err.toString();
}