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 {
|
9 | $customPath,
|
10 | $customCallback,
|
11 | $customConfiguration,
|
12 | $customTimestamp
|
13 | } = require('../symbols')
|
14 |
|
15 | module.exports = {
|
16 | schema: {
|
17 | custom: ['function', 'string'],
|
18 | watch: {
|
19 | type: 'boolean',
|
20 | defaultValue: false
|
21 | }
|
22 | },
|
23 | validate: async mapping => {
|
24 | if (typeof mapping.custom === 'string') {
|
25 | mapping[$customPath] = path.join(mapping.cwd, mapping.custom)
|
26 | mapping[$customCallback] = require(mapping[$customPath])
|
27 | if (mapping.watch) {
|
28 | mapping[$customTimestamp] = (await statAsync(mapping[$customPath])).mtimeMs
|
29 | }
|
30 | } else {
|
31 | mapping[$customCallback] = mapping.custom
|
32 | }
|
33 | if (typeof mapping[$customCallback] !== 'function') {
|
34 | throw new Error('Invalid custom handler, expected a function')
|
35 | }
|
36 | if (mapping.configuration === undefined) {
|
37 | mapping[$customConfiguration] = true
|
38 | }
|
39 | },
|
40 | redirect: async ({ configuration, mapping, match, request, response }) => {
|
41 | if (mapping[$customTimestamp]) {
|
42 | const timestamp = (await statAsync(mapping[$customPath])).mtimeMs
|
43 | if (timestamp !== mapping[$customTimestamp]) {
|
44 | mapping[$customTimestamp] = timestamp
|
45 | delete require.cache[mapping[$customPath]]
|
46 | mapping[$customCallback] = require(mapping[$customPath])
|
47 | }
|
48 | }
|
49 |
|
50 | const parameters = [request, response].concat([].slice.call(match, 1))
|
51 | if (mapping[$customConfiguration]) {
|
52 | mapping.configuration = configuration
|
53 | }
|
54 | return mapping[$customCallback].apply(mapping, parameters)
|
55 | }
|
56 | }
|