1 | 'use strict'
|
2 |
|
3 | const fs = require('fs')
|
4 | const path = require('path')
|
5 | const util = require('util')
|
6 | const statAsync = util.promisify(fs.stat)
|
7 |
|
8 | const { $customPath, $customCallback, $customTimestamp } = require('../symbols')
|
9 |
|
10 | module.exports = {
|
11 | schema: {
|
12 | custom: ['function', 'string'],
|
13 | watch: {
|
14 | type: 'boolean',
|
15 | defaultValue: false
|
16 | }
|
17 | },
|
18 | validate: async mapping => {
|
19 | if (typeof mapping.custom === 'string') {
|
20 | mapping[$customPath] = path.join(mapping.cwd, mapping.custom)
|
21 | mapping[$customCallback] = require(mapping[$customPath])
|
22 | if (mapping.watch) {
|
23 | mapping[$customTimestamp] = (await statAsync(mapping[$customPath])).mtimeMs
|
24 | }
|
25 | } else {
|
26 | mapping[$customCallback] = mapping.custom
|
27 | }
|
28 | if (typeof mapping[$customCallback] !== 'function') {
|
29 | throw new Error('Invalid custom handler, expected a function')
|
30 | }
|
31 | },
|
32 | redirect: async ({ mapping, match, request, response }) => {
|
33 | if (mapping[$customTimestamp]) {
|
34 | const timestamp = (await statAsync(mapping[$customPath])).mtimeMs
|
35 | if (timestamp !== mapping[$customTimestamp]) {
|
36 | mapping[$customTimestamp] = timestamp
|
37 | delete require.cache[mapping[$customPath]]
|
38 | mapping[$customCallback] = require(mapping[$customPath])
|
39 | }
|
40 | }
|
41 |
|
42 | const parameters = [request, response].concat([].slice.call(match, 1))
|
43 | return mapping[$customCallback].apply(mapping, parameters)
|
44 | }
|
45 | }
|