index.ts 3.7 KB
Newer Older
1 2
/* eslint-disable no-console */

3
import {config} from 'dotenv';
4
import express from 'express';
5
import {promises as fs} from 'fs';
6
import path from 'path';
7 8 9
import resolve from 'enhanced-resolve';

config();
10

11
const isDev = process.env.NODE_ENV === 'development';
P
Peter Pan 已提交
12
const isDemo = !!process.env.DEMO;
13

14
const host = process.env.HOST || 'localhost';
15
const port = Number.parseInt(process.env.PORT || '', 10) || 8999;
16
const backend = process.env.BACKEND;
17
const delay = Number.parseInt(process.env.DELAY || '', 10);
18
const pingUrl = process.env.PING_URL;
P
Peter Pan 已提交
19

20
const root = path.dirname(resolve.sync(__dirname, '@visualdl/core'));
21

22
const app = express();
23

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
async function parseTemplate() {
    const template = await fs.readFile(path.resolve(root, 'index.tpl.html'), {encoding: 'utf-8'});
    return template.replace(/%(.+?)%/g, (_matched, key) => process.env[key] ?? '');
}

async function extendEnv() {
    const content = await fs.readFile(path.resolve(root, '__snowpack__/env.local.js'), {encoding: 'utf-8'});
    const match = content.match(/export default\s*({.*})/);
    const env = JSON.parse(match[1]);
    return Object.keys(env).reduce((m, key) => {
        if (process.env[key] != null) {
            m[key] = process.env[key];
        }
        return m;
    }, env);
}

41
async function start() {
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
    require('@visualdl/core/builder/environment');

    // snowpack uses PUBLIC_URL & MODE in template
    // https://www.snowpack.dev/#environment-variables
    process.env.MODE = process.env.NODE_ENV;
    if (process.env.PUBLIC_PATH != null) {
        process.env.PUBLIC_URL = process.env.PUBLIC_PATH;
    }

    const baseUri = process.env.SNOWPACK_PUBLIC_BASE_URI;
    const apiUrl = process.env.SNOWPACK_PUBLIC_API_URL;

    const template = await parseTemplate();
    const env = await extendEnv();

57
    if (backend) {
P
Peter Pan 已提交
58
        const {createProxyMiddleware} = await import('http-proxy-middleware');
59 60
        app.use(
            apiUrl,
61 62 63 64 65
            createProxyMiddleware({
                target: backend,
                changeOrigin: true
            })
        );
P
Peter Pan 已提交
66
    } else if (isDemo) {
P
Peter Pan 已提交
67 68 69 70 71 72
        try {
            const {default: demo} = await import('@visualdl/demo');
            app.use(apiUrl, demo);
        } catch {
            console.warn('Demo is not installed. Please rebuild server.');
        }
P
Peter Pan 已提交
73
    } else if (isDev) {
74 75
        const {middleware: mock} = await import('@visualdl/mock');
        app.use(apiUrl, mock({delay: delay ? () => Math.random() * delay : 0}));
76 77
    } else {
        console.warn('Server is running in production mode but no backend address specified.');
78 79
    }

80
    if (baseUri !== '') {
81
        app.get('/', (_req, res) => {
82
            res.redirect(baseUri);
83 84 85
        });
    }

86
    if (pingUrl && pingUrl !== '/' && pingUrl !== baseUri && pingUrl.startsWith('/')) {
87
        app.get(pingUrl, (_req, res) => {
88
            res.type('text/plain').status(200).send('OK!');
P
Peter Pan 已提交
89 90 91
        });
    }

92 93 94 95 96 97 98
    app.get(`${baseUri}/__snowpack__/env.local.js`, (_req, res) => {
        res.type('.js')
            .status(200)
            .send(`export default ${JSON.stringify(env)};`);
    });

    app.use(baseUri || '/', express.static(root, {index: false}));
99

100
    app.get(/\.wasm/, (_req, res, next) => {
101 102 103 104
        res.type('application/wasm');
        next();
    });

105
    app.get('*', (_req, res) => {
106
        res.type('.html').status(200).send(template);
107
    });
108

109
    const server = app.listen(port, host, () => {
110 111 112
        process.send?.('ready');
        console.log(`> Ready on http://${host}:${port}`);
        process.on('SIGINT', () => {
113
            server.close(err => {
114 115 116 117 118 119 120
                if (err) {
                    throw err;
                }
                process.exit(0);
            });
        });
    });
121 122 123 124 125 126 127
}

if (require.main === module) {
    start();
}

export default start;
128

129
export {app};