@knapsack/app
Version:
Build Design Systems on top of knapsack, by Basalt
156 lines (139 loc) • 3.86 kB
text/typescript
import express from 'express';
import { readFile, existsSync } from 'fs-extra';
import { hbsRenderString } from '@knapsack/core';
import { join, dirname } from 'path';
import { apiUrlBase } from '../lib/constants';
import { createDemoUrl } from '../lib/routes';
import { KnapsackConfig } from '../schemas/knapsack-config';
const router = express.Router();
export function setupRoutes({
patterns,
knapsackDistDir,
distDir,
publicDir,
cacheDir,
plugins,
}: {
patterns: import('./patterns').Patterns;
knapsackDistDir: string;
distDir?: string;
publicDir?: string;
cacheDir: string;
plugins: KnapsackConfig['plugins'];
}): typeof router {
router.use('*', async (req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept',
);
next();
});
router.use(`${apiUrlBase}`, (req, res, next) => {
if (process.env.NODE_ENV === 'production') {
next();
} else {
// faking a slight delay in local development to better reflect re-world delays
setTimeout(next, 500);
}
});
router.use(
express.static(knapsackDistDir, {
maxAge: '1d',
}),
);
const designSystemDistDir = dirname(
require.resolve('@knapsack/design-system'),
);
router.use('/ks-design-system', express.static(designSystemDistDir));
if (distDir) {
router.use(
express.static(distDir, {
maxAge: '1d',
}),
);
}
if (cacheDir) {
router.use(
express.static(cacheDir, {
maxAge: '1d',
}),
);
}
if (publicDir) {
router.use(express.static(publicDir));
}
if (plugins) {
plugins
.filter(p => p.publicDir)
.forEach(plugin => {
router.use(`/plugins/${plugin.id}`, express.static(plugin.publicDir));
});
}
function getDemoUrls(): {
id: string;
title: string;
templates: {
id: string;
title: string;
demoUrls: string[];
}[];
}[] {
return patterns.getPatterns().map(pattern => {
return {
id: pattern.id,
title: pattern.title,
templates: pattern.templates.map(template => {
return {
id: template.id,
title: template.title ?? template.id,
demoUrls: [
...template.demos.map(demoId =>
createDemoUrl({
patternId: pattern.id,
templateId: template.id,
demoId,
wrapHtml: true,
isInIframe: false,
}),
),
],
};
}),
};
});
}
router.get('/demo-urls-data', (req, res) => {
res.send(getDemoUrls());
});
const demoUrlsHbsPath = join(__dirname, './templates/demo-urls.html.hbs');
if (!existsSync(demoUrlsHbsPath)) {
throw new Error(
`Demo URLs handlebars template does not exist: ${demoUrlsHbsPath}`,
);
}
// This page is mainly so IE can get a list of links to view the individual templates outside of the system
router.route('/demo-urls').get(async (req, res) => {
const patternDemos = getDemoUrls();
const demoUrlsHbs = await readFile(demoUrlsHbsPath, 'utf-8');
const result = hbsRenderString({
hbsString: demoUrlsHbs,
data: {
patternDemos,
},
});
res.send(result);
});
// Since this is a Single Page App, we will send all html requests to the `index.html` file in the dist
router.use('*', (req, res, next) => {
const { accept = '' } = req.headers;
const accepted = accept.split(',');
// this is for serving up a Netlify CMS folder if present
if (accepted.includes('text/html')) {
res.sendFile(join(knapsackDistDir, 'index.html'));
} else {
next();
}
});
return router;
}