gx
chenyc
2025-06-12 7b72ac13a83764a662159d4a49b7fffb90476ecb
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
'use strict';
 
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
var util = require('util');
var _require = require('triple-beam'),
  SPLAT = _require.SPLAT;
 
/**
 * Captures the number of format (i.e. %s strings) in a given string.
 * Based on `util.format`, see Node.js source:
 * https://github.com/nodejs/node/blob/b1c8f15c5f169e021f7c46eb7b219de95fe97603/lib/util.js#L201-L230
 * @type {RegExp}
 */
var formatRegExp = /%[scdjifoO%]/g;
 
/**
 * Captures the number of escaped % signs in a format string (i.e. %s strings).
 * @type {RegExp}
 */
var escapedPercent = /%%/g;
var Splatter = /*#__PURE__*/function () {
  function Splatter(opts) {
    _classCallCheck(this, Splatter);
    this.options = opts;
  }
 
  /**
     * Check to see if tokens <= splat.length, assign { splat, meta } into the
     * `info` accordingly, and write to this instance.
     *
     * @param  {Info} info Logform info message.
     * @param  {String[]} tokens Set of string interpolation tokens.
     * @returns {Info} Modified info message
     * @private
     */
  return _createClass(Splatter, [{
    key: "_splat",
    value: function _splat(info, tokens) {
      var msg = info.message;
      var splat = info[SPLAT] || info.splat || [];
      var percents = msg.match(escapedPercent);
      var escapes = percents && percents.length || 0;
 
      // The expected splat is the number of tokens minus the number of escapes
      // e.g.
      // - { expectedSplat: 3 } '%d %s %j'
      // - { expectedSplat: 5 } '[%s] %d%% %d%% %s %j'
      //
      // Any "meta" will be arugments in addition to the expected splat size
      // regardless of type. e.g.
      //
      // logger.log('info', '%d%% %s %j', 100, 'wow', { such: 'js' }, { thisIsMeta: true });
      // would result in splat of four (4), but only three (3) are expected. Therefore:
      //
      // extraSplat = 3 - 4 = -1
      // metas = [100, 'wow', { such: 'js' }, { thisIsMeta: true }].splice(-1, -1 * -1);
      // splat = [100, 'wow', { such: 'js' }]
      var expectedSplat = tokens.length - escapes;
      var extraSplat = expectedSplat - splat.length;
      var metas = extraSplat < 0 ? splat.splice(extraSplat, -1 * extraSplat) : [];
 
      // Now that { splat } has been separated from any potential { meta }. we
      // can assign this to the `info` object and write it to our format stream.
      // If the additional metas are **NOT** objects or **LACK** enumerable properties
      // you are going to have a bad time.
      var metalen = metas.length;
      if (metalen) {
        for (var i = 0; i < metalen; i++) {
          Object.assign(info, metas[i]);
        }
      }
      info.message = util.format.apply(util, [msg].concat(_toConsumableArray(splat)));
      return info;
    }
 
    /**
      * Transforms the `info` message by using `util.format` to complete
      * any `info.message` provided it has string interpolation tokens.
      * If no tokens exist then `info` is immutable.
      *
      * @param  {Info} info Logform info message.
      * @param  {Object} opts Options for this instance.
      * @returns {Info} Modified info message
      */
  }, {
    key: "transform",
    value: function transform(info) {
      var msg = info.message;
      var splat = info[SPLAT] || info.splat;
 
      // No need to process anything if splat is undefined
      if (!splat || !splat.length) {
        return info;
      }
 
      // Extract tokens, if none available default to empty array to
      // ensure consistancy in expected results
      var tokens = msg && msg.match && msg.match(formatRegExp);
 
      // This condition will take care of inputs with info[SPLAT]
      // but no tokens present
      if (!tokens && (splat || splat.length)) {
        var metas = splat.length > 1 ? splat.splice(0) : splat;
 
        // Now that { splat } has been separated from any potential { meta }. we
        // can assign this to the `info` object and write it to our format stream.
        // If the additional metas are **NOT** objects or **LACK** enumerable properties
        // you are going to have a bad time.
        var metalen = metas.length;
        if (metalen) {
          for (var i = 0; i < metalen; i++) {
            Object.assign(info, metas[i]);
          }
        }
        return info;
      }
      if (tokens) {
        return this._splat(info, tokens);
      }
      return info;
    }
  }]);
}();
/*
 * function splat (info)
 * Returns a new instance of the splat format TransformStream
 * which performs string interpolation from `info` objects. This was
 * previously exposed implicitly in `winston < 3.0.0`.
 */
module.exports = function (opts) {
  return new Splatter(opts);
};