forked from indexzero/morgan-json
-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
92 lines (75 loc) · 2.92 KB
/
index.js
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
'use strict';
var debug = require('diagnostics')('morgan-json');
/**
* Compile a `morgan` format string into a `morgan` format function
* that returns JSON.
*
* Adopted from `morgan.compile` from `morgan` under MIT.
*
* @param {string|Object} format
* @param {Object} opts Options for how things are returned.
* - 'stringify': (default: true) If false returns an object literal
* @return {function}
* @public
*/
module.exports = function compile (format, opts) {
if (format === '') {
throw new Error('argument format string must not be empty');
}
if (typeof format !== 'string') {
return compileObject(format, opts);
}
opts = opts || {};
var fmt = format
.replace(/"/g, '\\"')
// remove everything until the first valid token
.replace(/^.*?(?=:)|.*/, '');
var stringify = opts.stringify !== false ? 'JSON.stringify' : '';
var js = ' "use strict"\n return ' + stringify + '({' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?([^:]+)?/g, function (_, name, arg, trail, offset, str) {
var tokenName = String(JSON.stringify(name));
var tokenArguments = 'req, res';
var tokenFunction = 'tokens[' + tokenName + ']';
var trailer = (trail || '').trimRight();
if (arg !== undefined) {
tokenArguments += ', ' + String(JSON.stringify(arg));
}
return '\n ' + tokenName + ': (' + tokenFunction + '(' + tokenArguments + ') || "-") + ' + JSON.stringify(trailer) + ','
}) + '\n })';
debug('\n%s', js);
// eslint-disable-next-line no-new-func
return new Function('tokens, req, res', js);
}
/**
* Compile an Object with keys as `morgan` format strings into a `morgan` format function
* that returns JSON. The JSON returned will have the same keys as the format Object.
*
* Adopted from `morgan.compile` from `morgan` under MIT.
*
* @param {string|Object} format
* @param {Object} opts Options for how things are returned.
* - 'stringify': (default: true) If false returns an object literal
* @return {function}
* @public
*/
function compileObject (format, opts) {
if (!format || typeof format !== 'object') {
throw new Error('argument format must be a string or an object');
}
opts = opts || {};
var keys = Object.keys(format);
var stringify = opts.stringify !== false ? 'JSON.stringify' : '';
var js = ' "use strict"\n return ' + stringify + '({' + keys.map(function (key, i) {
var assignment = '\n "' + key + '": "' + format[key].replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function (_, name, arg) {
var tokenArguments = 'req, res';
var tokenFunction = 'tokens[' + String(JSON.stringify(name)) + ']';
if (arg !== undefined) {
tokenArguments += ', ' + String(JSON.stringify(arg));
}
return '" + (' + tokenFunction + '(' + tokenArguments + ') || "-") + "';
}) + '"';
return assignment;
}) + '\n })';
debug('\n%s', js);
// eslint-disable-next-line no-new-func
return new Function('tokens, req, res', js);
};