@wireio/shared 1.0.21 → 1.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/lib/cjs/errors/NestedError.d.ts +10 -0
  2. package/lib/cjs/errors/NestedError.d.ts.map +1 -0
  3. package/lib/cjs/errors/NestedError.js +24 -0
  4. package/lib/cjs/errors/index.d.ts +2 -0
  5. package/lib/cjs/errors/index.d.ts.map +1 -0
  6. package/lib/cjs/errors/index.js +18 -0
  7. package/lib/cjs/guards/applyTypeGuardExtras.d.ts +1 -1
  8. package/lib/cjs/guards/applyTypeGuardExtras.d.ts.map +1 -1
  9. package/lib/cjs/guards/applyTypeGuardExtras.js +1 -1
  10. package/lib/cjs/guards/class.d.ts +1 -1
  11. package/lib/cjs/guards/class.d.ts.map +1 -1
  12. package/lib/cjs/guards/class.js +1 -1
  13. package/lib/cjs/helpers/Deferred.d.ts +81 -0
  14. package/lib/cjs/helpers/Deferred.d.ts.map +1 -1
  15. package/lib/cjs/helpers/Deferred.js +100 -5
  16. package/lib/cjs/index.d.ts +1 -0
  17. package/lib/cjs/index.d.ts.map +1 -1
  18. package/lib/cjs/index.js +2 -1
  19. package/lib/cjs/logging/Formatter.d.ts +1 -1
  20. package/lib/cjs/logging/Formatter.d.ts.map +1 -1
  21. package/lib/cjs/logging/Formatter.js +1 -1
  22. package/lib/cjs/logging/Level.d.ts.map +1 -1
  23. package/lib/cjs/logging/Level.js +3 -4
  24. package/lib/cjs/logging/Logger.d.ts.map +1 -1
  25. package/lib/cjs/logging/Logger.js +2 -2
  26. package/lib/cjs/logging/appenders/ConsoleAppender.d.ts +4 -4
  27. package/lib/cjs/logging/appenders/ConsoleAppender.d.ts.map +1 -1
  28. package/lib/cjs/logging/appenders/ConsoleAppender.js +1 -1
  29. package/lib/cjs/logging/context/LogContextProvider.d.ts +1 -1
  30. package/lib/cjs/logging/context/LogContextProvider.d.ts.map +1 -1
  31. package/lib/cjs/logging/context/LogContextProvider.js +1 -1
  32. package/lib/cjs/logging/context/providers/node/NodeContextProvider.js +1 -1
  33. package/lib/cjs/logging/examples/example-file-appender.js +2 -2
  34. package/lib/cjs/logging/getLogger.d.ts +1 -1
  35. package/lib/cjs/logging/getLogger.d.ts.map +1 -1
  36. package/lib/cjs/logging/getLogger.js +1 -1
  37. package/lib/cjs/logging/index-node.d.ts +1 -1
  38. package/lib/cjs/logging/index-node.d.ts.map +1 -1
  39. package/lib/cjs/logging/index-node.js +2 -2
  40. package/lib/cjs/node/index.d.ts +3 -0
  41. package/lib/cjs/node/index.d.ts.map +1 -0
  42. package/lib/cjs/node/index.js +19 -0
  43. package/lib/cjs/{logging → node/logging}/appenders/FileAppender.d.ts +2 -2
  44. package/lib/cjs/node/logging/appenders/FileAppender.d.ts.map +1 -0
  45. package/lib/cjs/node/logging/appenders/FileAppender.js +254 -0
  46. package/lib/cjs/node/logging/appenders/index.d.ts +3 -0
  47. package/lib/cjs/node/logging/appenders/index.d.ts.map +1 -0
  48. package/lib/cjs/node/logging/appenders/index.js +19 -0
  49. package/lib/esm/errors/NestedError.d.ts +10 -0
  50. package/lib/esm/errors/NestedError.d.ts.map +1 -0
  51. package/lib/esm/errors/NestedError.js +20 -0
  52. package/lib/esm/errors/index.d.ts +2 -0
  53. package/lib/esm/errors/index.d.ts.map +1 -0
  54. package/lib/esm/errors/index.js +2 -0
  55. package/lib/esm/guards/applyTypeGuardExtras.d.ts +1 -1
  56. package/lib/esm/guards/applyTypeGuardExtras.d.ts.map +1 -1
  57. package/lib/esm/guards/applyTypeGuardExtras.js +1 -1
  58. package/lib/esm/guards/class.d.ts +1 -1
  59. package/lib/esm/guards/class.d.ts.map +1 -1
  60. package/lib/esm/guards/class.js +1 -1
  61. package/lib/esm/helpers/Deferred.d.ts +81 -0
  62. package/lib/esm/helpers/Deferred.d.ts.map +1 -1
  63. package/lib/esm/helpers/Deferred.js +100 -5
  64. package/lib/esm/index.d.ts +1 -0
  65. package/lib/esm/index.d.ts.map +1 -1
  66. package/lib/esm/index.js +2 -1
  67. package/lib/esm/logging/Formatter.d.ts +1 -1
  68. package/lib/esm/logging/Formatter.d.ts.map +1 -1
  69. package/lib/esm/logging/Formatter.js +1 -1
  70. package/lib/esm/logging/Level.d.ts.map +1 -1
  71. package/lib/esm/logging/Level.js +3 -4
  72. package/lib/esm/logging/Logger.d.ts.map +1 -1
  73. package/lib/esm/logging/Logger.js +3 -3
  74. package/lib/esm/logging/appenders/ConsoleAppender.d.ts +4 -4
  75. package/lib/esm/logging/appenders/ConsoleAppender.d.ts.map +1 -1
  76. package/lib/esm/logging/appenders/ConsoleAppender.js +1 -1
  77. package/lib/esm/logging/context/LogContextProvider.d.ts +1 -1
  78. package/lib/esm/logging/context/LogContextProvider.d.ts.map +1 -1
  79. package/lib/esm/logging/context/LogContextProvider.js +1 -1
  80. package/lib/esm/logging/context/providers/node/NodeContextProvider.js +1 -1
  81. package/lib/esm/logging/examples/example-file-appender.js +2 -2
  82. package/lib/esm/logging/getLogger.d.ts +1 -1
  83. package/lib/esm/logging/getLogger.d.ts.map +1 -1
  84. package/lib/esm/logging/getLogger.js +1 -1
  85. package/lib/esm/logging/index-node.d.ts +1 -1
  86. package/lib/esm/logging/index-node.d.ts.map +1 -1
  87. package/lib/esm/logging/index-node.js +2 -2
  88. package/lib/esm/node/index.d.ts +3 -0
  89. package/lib/esm/node/index.d.ts.map +1 -0
  90. package/lib/esm/node/index.js +3 -0
  91. package/lib/esm/{logging → node/logging}/appenders/FileAppender.d.ts +2 -2
  92. package/lib/esm/node/logging/appenders/FileAppender.d.ts.map +1 -0
  93. package/lib/esm/node/logging/appenders/FileAppender.js +214 -0
  94. package/lib/esm/node/logging/appenders/index.d.ts +3 -0
  95. package/lib/esm/node/logging/appenders/index.d.ts.map +1 -0
  96. package/lib/esm/node/logging/appenders/index.js +3 -0
  97. package/lib/tsconfig.cjs.jest.tsbuildinfo +1 -1
  98. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  99. package/lib/tsconfig.esm.tsbuildinfo +1 -1
  100. package/package.json +15 -9
  101. package/lib/cjs/logging/appenders/FileAppender.d.ts.map +0 -1
  102. package/lib/cjs/logging/appenders/FileAppender.js +0 -254
  103. package/lib/esm/logging/appenders/FileAppender.d.ts.map +0 -1
  104. package/lib/esm/logging/appenders/FileAppender.js +0 -214
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wireio/shared",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -14,14 +14,19 @@
14
14
  "module": "lib/esm/index.js",
15
15
  "exports": {
16
16
  ".": {
17
+ "types": "./lib/esm/index.d.ts",
17
18
  "import": "./lib/esm/index.js",
18
- "require": "./lib/cjs/index.js",
19
- "types": "./lib/esm/index.d.ts"
19
+ "require": "./lib/cjs/index.js"
20
+ },
21
+ "./node": {
22
+ "types": "./lib/esm/node/index.d.ts",
23
+ "import": "./lib/esm/node/index.js",
24
+ "require": "./lib/cjs/node/index.js"
20
25
  },
21
26
  "./*": {
27
+ "types": "./lib/esm/*.d.ts",
22
28
  "import": "./lib/esm/*.js",
23
- "require": "./lib/cjs/*.js",
24
- "types": "./lib/esm/*.d.ts"
29
+ "require": "./lib/cjs/*.js"
25
30
  }
26
31
  },
27
32
  "access": "public",
@@ -36,13 +41,14 @@
36
41
  "bluebird": "3.7.2",
37
42
  "debug": "^4.3.4",
38
43
  "eventemitter3": "^5.0.4",
39
- "lodash": "^4.17.21",
44
+ "lodash": "^4.18.1",
40
45
  "@3fv/prelude-ts": "^0.8.37",
41
46
  "tracer": "^1.3.0"
42
47
  },
43
48
  "scripts": {
44
- "build": "tsc -b tsconfig.json && node ../../scripts/fix-hybrid-output.mjs .",
45
- "build:dev": "tsc -b tsconfig.json -w",
46
- "test": "jest"
49
+ "compile": "tsc -b tsconfig.json",
50
+ "compile:watch": "tsc -b tsconfig.json -w",
51
+ "build": "pnpm run compile && node ../../scripts/fix-hybrid-output.mjs .",
52
+ "test": "pnpm run build && jest"
47
53
  }
48
54
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"FileAppender.d.ts","sourceRoot":"","sources":["../../../../src/logging/appenders/FileAppender.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAsB/B,MAAM,WAAW,kBAAkB,CAAC,MAAM,SAAS,SAAS,GAAG,GAAG;IAChE,QAAQ,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf,aAAa,EAAE,OAAO,CAAA;IACtB,WAAW,EAAE,OAAO,CAAA;IACpB,IAAI,EAAE,OAAO,CAAA;CACd;AAED,MAAM,MAAM,mBAAmB,CAAC,MAAM,SAAS,SAAS,GAAG,GAAG,IAAI,OAAO,CACvE,kBAAkB,CAAC,MAAM,CAAC,CAC3B,CAAA;AAED,qBAAa,YAAY,CACvB,MAAM,SAAS,SAAS,CACxB,YAAW,QAAQ,CAAC,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAA;IAE3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAiBrB;IAED,IAAI,aAAa,YAEhB;IAED,OAAO;IAIP;;;;OAIG;IACH,KAAK,IAAI,YAAY,CAAC,MAAM,CAAC;IA2B7B;;;;;;;OAOG;IACH,QAAQ;IAkDR;;;;OAIG;IACH,KAAK;IAML,IAAI,KAAK,8BAER;IAED,IAAI,IAAI,WAEP;IAED,IAAI,QAAQ,YAEX;IAED,IAAI,QAAQ,WAEX;IAED;;OAEG;IACH,OAAO,CAAC,KAAK;IAoCb;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAsB5B;;;OAGG;gBACS,OAAO,GAAE,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAM;CAW/D"}
@@ -1,254 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.FileAppender = void 0;
40
- const lodash_1 = require("lodash");
41
- const Path = __importStar(require("path"));
42
- const Fs = __importStar(require("fs"));
43
- const prelude_ts_1 = require("@3fv/prelude-ts");
44
- const buffer_1 = require("buffer");
45
- const debug_1 = __importDefault(require("debug"));
46
- const bluebird_1 = __importDefault(require("bluebird"));
47
- const FsAsync = Fs.promises;
48
- const debug = (0, debug_1.default)("3fv:logger:FileAppender");
49
- const osTempDir = process.env.TMP ?? process.env.TEMP ?? "/tmp";
50
- const tempDir = Fs.mkdtempSync(Path.join(osTempDir, "logger-proxy-example")); //
51
- const getDefaultConfig = () => ({
52
- filename: Path.join(tempDir, "app.log"),
53
- prettyPrint: process.env.NODE_ENV !== "production",
54
- maxSize: -1,
55
- maxFiles: 5,
56
- enableRolling: false,
57
- sync: false
58
- });
59
- function applyConfigDefaults(options) {
60
- return (0, lodash_1.defaults)(options, getDefaultConfig());
61
- }
62
- class FileAppender {
63
- config;
64
- state = {
65
- archivedFilenames: [],
66
- filename: undefined,
67
- file: undefined,
68
- ready: false,
69
- currentSize: 0,
70
- flushing: false,
71
- queue: []
72
- };
73
- get enableRolling() {
74
- return this.config.enableRolling;
75
- }
76
- isReady() {
77
- return this.state.ready;
78
- }
79
- /**
80
- * Initialize and setup the appender
81
- *
82
- * @returns {FileAppender<Record>}
83
- */
84
- setup() {
85
- const { state } = this;
86
- if (!!state.ready) {
87
- return this;
88
- }
89
- try {
90
- const { filename } = this;
91
- const file = Fs.openSync(filename, "a");
92
- (0, lodash_1.assign)(state, {
93
- filename,
94
- file,
95
- ready: true
96
- });
97
- return this;
98
- }
99
- catch (err) {
100
- (0, lodash_1.assign)(state, {
101
- error: err,
102
- file: undefined,
103
- ready: false
104
- });
105
- throw err;
106
- }
107
- }
108
- /**
109
- * Only exposed for the sake of tests & examples
110
- * DO NOT USE
111
- *
112
- * This should all be async, but i was in a rush :(
113
- *
114
- * @returns
115
- */
116
- rollFile() {
117
- const { state, config } = this;
118
- let { file, filename, archivedFilenames } = state;
119
- if (!this.isReady() || !file) {
120
- debug(`Can not roll file before ready`);
121
- return;
122
- }
123
- if (!this.enableRolling) {
124
- return;
125
- }
126
- const fileCount = archivedFilenames.length + 1;
127
- if (config.maxFiles < 1 || fileCount < config.maxFiles) {
128
- archivedFilenames.push(filename + "." + (0, lodash_1.padStart)(fileCount.toString(10), 4, "0"));
129
- }
130
- Fs.fdatasyncSync(file);
131
- Fs.closeSync(file);
132
- file = state.file = undefined;
133
- const filenames = [filename, ...archivedFilenames];
134
- let dest = filenames.pop();
135
- while (filenames.length) {
136
- let src = filenames.pop();
137
- if (!Fs.existsSync(src)) {
138
- debug(`src does not exist, skipping ${src}`);
139
- }
140
- else {
141
- debug(`Moving src (${src}) to dest (${dest})`);
142
- if (Fs.existsSync(dest)) {
143
- Fs.unlinkSync(dest);
144
- }
145
- Fs.renameSync(src, dest);
146
- // if (src === filename) {
147
- // Fs.copyFileSync(src, dest)
148
- // Fs.truncateSync(src, 0)
149
- // } else {
150
- // Fs.renameSync(src, dest)
151
- // }
152
- }
153
- dest = src;
154
- }
155
- (0, lodash_1.assign)(state, {
156
- currentSize: 0,
157
- file: Fs.openSync(filename, "a")
158
- });
159
- }
160
- /**
161
- * Close the handler
162
- *
163
- * @returns {Promise<void>}
164
- */
165
- close() {
166
- return this.flush()
167
- .onComplete(() => prelude_ts_1.Option.of(this.state.file).map(Fs.closeSync))
168
- .toPromise();
169
- }
170
- get queue() {
171
- return this.state.queue;
172
- }
173
- get file() {
174
- return this.state.file;
175
- }
176
- get flushing() {
177
- return this.state.flushing;
178
- }
179
- get filename() {
180
- return (this.state.filename = this.state.filename ?? this.config.filename);
181
- }
182
- /**
183
- * Appends the log queue records to the file
184
- */
185
- flush() {
186
- const { state } = this;
187
- return prelude_ts_1.Future.do(async () => {
188
- state.flushing = true;
189
- try {
190
- const { file } = this;
191
- if (!file) {
192
- throw Error(`${this.filename} was not opened properly`);
193
- }
194
- while (this.queue.length) {
195
- const buf = this.queue.shift();
196
- await bluebird_1.default.fromCallback(cb => Fs.appendFile(file, buf, "utf-8", cb));
197
- state.currentSize += buf.byteLength;
198
- }
199
- const { maxSize } = this.config;
200
- if (maxSize > 0 && state.currentSize >= maxSize) {
201
- this.rollFile();
202
- }
203
- //await Bluebird.fromCallback((cb) => Fs.fdatasync(this.file, cb))
204
- }
205
- catch (err) {
206
- console.error(`Failed to append file ${this.filename}`, err);
207
- }
208
- finally {
209
- this.state.flushing = false;
210
- if (this.queue.length) {
211
- queueMicrotask(() => this.flush());
212
- }
213
- }
214
- });
215
- }
216
- /**
217
- * Handle log records, transform, push to ES
218
- *
219
- * @param record
220
- */
221
- append(record) {
222
- try {
223
- const { queue, filename } = this.state;
224
- const count = queue.length;
225
- if (count > 999) {
226
- debug(`Too many log records (${count}) are in the queue without the file (${filename}) opening, skipping %O`, record);
227
- return;
228
- }
229
- const data = this.config.prettyPrint
230
- ? JSON.stringify(record, null, 2)
231
- : JSON.stringify(record);
232
- queue.push(buffer_1.Buffer.from(data + "\n", "utf-8"));
233
- this.flush();
234
- }
235
- catch (err) {
236
- console.warn(`Failed to synchronize `, err);
237
- }
238
- }
239
- /**
240
- *
241
- * @param {Partial<FileAppenderOptions<Record>>} options
242
- */
243
- constructor(options = {}) {
244
- this.config = applyConfigDefaults(options);
245
- (0, lodash_1.assign)(this.state, {
246
- filename: this.config.filename
247
- });
248
- this.setup();
249
- debug(`File appender is ready, logging to ${this.state.filename}`);
250
- // return this
251
- }
252
- }
253
- exports.FileAppender = FileAppender;
254
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlsZUFwcGVuZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xvZ2dpbmcvYXBwZW5kZXJzL0ZpbGVBcHBlbmRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxtQ0FBbUQ7QUFDbkQsMkNBQTRCO0FBQzVCLHVDQUF3QjtBQUd4QixnREFBZ0Q7QUFDaEQsbUNBQStCO0FBQy9CLGtEQUF5QjtBQUN6Qix3REFBK0I7QUFFL0IsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQTtBQUUzQixNQUFNLEtBQUssR0FBRyxJQUFBLGVBQUssRUFBQyx5QkFBeUIsQ0FBQyxDQUFBO0FBQzlDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQTtBQUMvRCxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLHNCQUFzQixDQUFDLENBQUMsQ0FBQSxDQUFDLEVBQUU7QUFDL0UsTUFBTSxnQkFBZ0IsR0FBRyxHQUF1QixFQUFFLENBQUMsQ0FBQztJQUNsRCxRQUFRLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDO0lBQ3ZDLFdBQVcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsS0FBSyxZQUFZO0lBQ2xELE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDWCxRQUFRLEVBQUUsQ0FBQztJQUNYLGFBQWEsRUFBRSxLQUFLO0lBQ3BCLElBQUksRUFBRSxLQUFLO0NBQ1osQ0FBQyxDQUFBO0FBRUYsU0FBUyxtQkFBbUIsQ0FBQyxPQUE0QjtJQUN2RCxPQUFPLElBQUEsaUJBQVEsRUFBQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFBO0FB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QUMsSUFBSSxHQUFHLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFBO1lBQzdDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNkLENBQUM7UUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2IsT0FBTyxDQUFDLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxHQUFHLENBQUMsQ0FBQTtRQUM3QyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILFlBQVksVUFBZ0QsRUFBRTtRQUM1RCxJQUFJLENBQUMsTUFBTSxHQUFHLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBRTFDLElBQUEsZUFBTSxFQUFDLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDakIsUUFBUSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUTtTQUMvQixDQUFDLENBQUE7UUFFRixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDWixLQUFLLENBQUMsc0NBQXNDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQTtRQUNsRSxtQkFBbUI7SUFDckIsQ0FBQztDQUNGO0FBdE9ELG9DQXNPQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGFzc2lnbiwgZGVmYXVsdHMsIHBhZFN0YXJ0IH0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQgKiBhcyBQYXRoIGZyb20gXCJwYXRoXCJcbmltcG9ydCAqIGFzIEZzIGZyb20gXCJmc1wiXG5pbXBvcnQgdHlwZSB7IExvZ1JlY29yZCB9IGZyb20gXCIuLi9Mb2dSZWNvcmRcIlxuaW1wb3J0IHR5cGUgeyBBcHBlbmRlciB9IGZyb20gXCIuLi9BcHBlbmRlclwiXG5pbXBvcnQgeyBPcHRpb24sIEZ1dHVyZSB9IGZyb20gXCJAM2Z2L3ByZWx1ZGUtdHNcIlxuaW1wb3J0IHsgQnVmZmVyIH0gZnJvbSBcImJ1ZmZlclwiXG5pbXBvcnQgRGVidWcgZnJvbSBcImRlYnVnXCJcbmltcG9ydCBCbHVlYmlyZCBmcm9tIFwiYmx1ZWJpcmRcIlxuXG5jb25zdCBGc0FzeW5jID0gRnMucHJvbWlzZXNcblxuY29uc3QgZGVidWcgPSBEZWJ1ZyhcIjNmdjpsb2dnZXI6RmlsZUFwcGVuZGVyXCIpXG5jb25zdCBvc1RlbXBEaXIgPSBwcm9jZXNzLmVudi5UTVAgPz8gcHJvY2Vzcy5lbnYuVEVNUCA/PyBcIi90bXBcIlxuY29uc3QgdGVtcERpciA9IEZzLm1rZHRlbXBTeW5jKFBhdGguam9pbihvc1RlbXBEaXIsIFwibG9nZ2VyLXByb3h5LWV4YW1wbGVcIikpIC8vXG5jb25zdCBnZXREZWZhdWx0Q29uZmlnID0gKCk6IEZpbGVBcHBlbmRlckNvbmZpZyA9PiAoe1xuICBmaWxlbmFtZTogUGF0aC5qb2luKHRlbXBEaXIsIFwiYXBwLmxvZ1wiKSxcbiAgcHJldHR5UHJpbnQ6IHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSBcInByb2R1Y3Rpb25cIixcbiAgbWF4U2l6ZTogLTEsXG4gIG1heEZpbGVzOiA1LFxuICBlbmFibGVSb2xsaW5nOiBmYWxzZSxcbiAgc3luYzogZmFsc2Vcbn0pXG5cbmZ1bmN0aW9uIGFwcGx5Q29uZmlnRGVmYXVsdHMob3B0aW9uczogRmlsZUFwcGVuZGVyT3B0aW9ucyk6IEZpbGVBcHBlbmRlckNvbmZpZyB7XG4gIHJldHVybiBkZWZhdWx0cyhvcHRpb25zLCBnZXREZWZhdWx0Q29uZmlnKCkpXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmlsZUFwcGVuZGVyQ29uZmlnPFJlY29yZCBleHRlbmRzIExvZ1JlY29yZCA9IGFueT4ge1xuICBmaWxlbmFtZTogc3RyaW5nXG5cbiAgLyoqXG4gICAqIEZvciByb2xsaW5nXG4gICAqL1xuICBtYXhGaWxlczogbnVtYmVyXG5cbiAgLyoqXG4gICAqIEZvciByb2xsaW5nXG4gICAqL1xuICBtYXhTaXplOiBudW1iZXJcblxuICBlbmFibGVSb2xsaW5nOiBib29sZWFuXG4gIHByZXR0eVByaW50OiBib29sZWFuXG4gIHN5bmM6IGJvb2xlYW5cbn1cblxuZXhwb3J0IHR5cGUgRmlsZUFwcGVuZGVyT3B0aW9uczxSZWNvcmQgZXh0ZW5kcyBMb2dSZWNvcmQgPSBhbnk+ID0gUGFydGlhbDxcbiAgRmlsZUFwcGVuZGVyQ29uZmlnPFJlY29yZD5cbj5cblxuZXhwb3J0IGNsYXNzIEZpbGVBcHBlbmRlcjxcbiAgUmVjb3JkIGV4dGVuZHMgTG9nUmVjb3JkXG4+IGltcGxlbWVudHMgQXBwZW5kZXI8UmVjb3JkPiB7XG4gIHJlYWRvbmx5IGNvbmZpZzogRmlsZUFwcGVuZGVyQ29uZmlnPFJlY29yZD5cblxuICBwcml2YXRlIHJlYWRvbmx5IHN0YXRlOiB7XG4gICAgZmlsZW5hbWU6IHN0cmluZ1xuICAgIGZpbGU6IG51bWJlclxuICAgIGZsdXNoaW5nOiBib29sZWFuXG4gICAgcXVldWU6IEFycmF5PEJ1ZmZlcj5cbiAgICByZWFkeTogYm9vbGVhblxuICAgIGVycm9yPzogRXJyb3JcbiAgICBjdXJyZW50U2l6ZTogbnVtYmVyXG4gICAgYXJjaGl2ZWRGaWxlbmFtZXM6IHN0cmluZ1tdXG4gIH0gPSB7XG4gICAgYXJjaGl2ZWRGaWxlbmFtZXM6IFtdLFxuICAgIGZpbGVuYW1lOiB1bmRlZmluZWQsXG4gICAgZmlsZTogdW5kZWZpbmVkLFxuICAgIHJlYWR5OiBmYWxzZSxcbiAgICBjdXJyZW50U2l6ZTogMCxcbiAgICBmbHVzaGluZzogZmFsc2UsXG4gICAgcXVldWU6IFtdXG4gIH1cblxuICBnZXQgZW5hYmxlUm9sbGluZygpIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZW5hYmxlUm9sbGluZ1xuICB9XG5cbiAgaXNSZWFkeSgpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5yZWFkeVxuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgYW5kIHNldHVwIHRoZSBhcHBlbmRlclxuICAgKlxuICAgKiBAcmV0dXJucyB7RmlsZUFwcGVuZGVyPFJlY29yZD59XG4gICAqL1xuICBzZXR1cCgpOiBGaWxlQXBwZW5kZXI8UmVjb3JkPiB7XG4gICAgY29uc3QgeyBzdGF0ZSB9ID0gdGhpc1xuICAgIGlmICghIXN0YXRlLnJlYWR5KSB7XG4gICAgICByZXR1cm4gdGhpc1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IGZpbGVuYW1lIH0gPSB0aGlzXG4gICAgICBjb25zdCBmaWxlID0gRnMub3BlblN5bmMoZmlsZW5hbWUsIFwiYVwiKVxuXG4gICAgICBhc3NpZ24oc3RhdGUsIHtcbiAgICAgICAgZmlsZW5hbWUsXG4gICAgICAgIGZpbGUsXG4gICAgICAgIHJlYWR5OiB0cnVlXG4gICAgICB9KVxuXG4gICAgICByZXR1cm4gdGhpc1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgYXNzaWduKHN0YXRlLCB7XG4gICAgICAgIGVycm9yOiBlcnIsXG4gICAgICAgIGZpbGU6IHVuZGVmaW5lZCxcbiAgICAgICAgcmVhZHk6IGZhbHNlXG4gICAgICB9KVxuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE9ubHkgZXhwb3NlZCBmb3IgdGhlIHNha2Ugb2YgdGVzdHMgJiBleGFtcGxlc1xuICAgKiBETyBOT1QgVVNFXG4gICAqXG4gICAqIFRoaXMgc2hvdWxkIGFsbCBiZSBhc3luYywgYnV0IGkgd2FzIGluIGEgcnVzaCA6KFxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgcm9sbEZpbGUoKSB7XG4gICAgY29uc3QgeyBzdGF0ZSwgY29uZmlnIH0gPSB0aGlzXG4gICAgbGV0IHsgZmlsZSwgZmlsZW5hbWUsIGFyY2hpdmVkRmlsZW5hbWVzIH0gPSBzdGF0ZVxuICAgIGlmICghdGhpcy5pc1JlYWR5KCkgfHwgIWZpbGUpIHtcbiAgICAgIGRlYnVnKGBDYW4gbm90IHJvbGwgZmlsZSBiZWZvcmUgcmVhZHlgKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmVuYWJsZVJvbGxpbmcpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IGZpbGVDb3VudCA9IGFyY2hpdmVkRmlsZW5hbWVzLmxlbmd0aCArIDFcbiAgICBpZiAoY29uZmlnLm1heEZpbGVzIDwgMSB8fCBmaWxlQ291bnQgPCBjb25maWcubWF4RmlsZXMpIHtcbiAgICAgIGFyY2hpdmVkRmlsZW5hbWVzLnB1c2goXG4gICAgICAgIGZpbGVuYW1lICsgXCIuXCIgKyBwYWRTdGFydChmaWxlQ291bnQudG9TdHJpbmcoMTApLCA0LCBcIjBcIilcbiAgICAgIClcbiAgICB9XG4gICAgRnMuZmRhdGFzeW5jU3luYyhmaWxlKVxuICAgIEZzLmNsb3NlU3luYyhmaWxlKVxuICAgIGZpbGUgPSBzdGF0ZS5maWxlID0gdW5kZWZpbmVkXG4gICAgY29uc3QgZmlsZW5hbWVzID0gW2ZpbGVuYW1lLCAuLi5hcmNoaXZlZEZpbGVuYW1lc11cblxuICAgIGxldCBkZXN0OiBzdHJpbmcgPSBmaWxlbmFtZXMucG9wKClcbiAgICB3aGlsZSAoZmlsZW5hbWVzLmxlbmd0aCkge1xuICAgICAgbGV0IHNyYyA9IGZpbGVuYW1lcy5wb3AoKVxuICAgICAgaWYgKCFGcy5leGlzdHNTeW5jKHNyYykpIHtcbiAgICAgICAgZGVidWcoYHNyYyBkb2VzIG5vdCBleGlzdCwgc2tpcHBpbmcgJHtzcmN9YClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlYnVnKGBNb3Zpbmcgc3JjICgke3NyY30pIHRvIGRlc3QgKCR7ZGVzdH0pYClcbiAgICAgICAgaWYgKEZzLmV4aXN0c1N5bmMoZGVzdCkpIHtcbiAgICAgICAgICBGcy51bmxpbmtTeW5jKGRlc3QpXG4gICAgICAgIH1cbiAgICAgICAgRnMucmVuYW1lU3luYyhzcmMsIGRlc3QpXG4gICAgICAgIC8vIGlmIChzcmMgPT09IGZpbGVuYW1lKSB7XG4gICAgICAgIC8vICAgRnMuY29weUZpbGVTeW5jKHNyYywgZGVzdClcbiAgICAgICAgLy8gICBGcy50cnVuY2F0ZVN5bmMoc3JjLCAwKVxuICAgICAgICAvLyB9IGVsc2Uge1xuICAgICAgICAvLyAgIEZzLnJlbmFtZVN5bmMoc3JjLCBkZXN0KVxuICAgICAgICAvLyB9XG4gICAgICB9XG4gICAgICBkZXN0ID0gc3JjXG4gICAgfVxuXG4gICAgYXNzaWduKHN0YXRlLCB7XG4gICAgICBjdXJyZW50U2l6ZTogMCxcbiAgICAgIGZpbGU6IEZzLm9wZW5TeW5jKGZpbGVuYW1lLCBcImFcIilcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIHRoZSBoYW5kbGVyXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmx1c2goKVxuICAgICAgLm9uQ29tcGxldGUoKCkgPT4gT3B0aW9uLm9mKHRoaXMuc3RhdGUuZmlsZSkubWFwKEZzLmNsb3NlU3luYykpXG4gICAgICAudG9Qcm9taXNlKClcbiAgfVxuXG4gIGdldCBxdWV1ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5xdWV1ZVxuICB9XG5cbiAgZ2V0IGZpbGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGUuZmlsZVxuICB9XG5cbiAgZ2V0IGZsdXNoaW5nKCkge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLmZsdXNoaW5nXG4gIH1cblxuICBnZXQgZmlsZW5hbWUoKSB7XG4gICAgcmV0dXJuICh0aGlzLnN0YXRlLmZpbGVuYW1lID0gdGhpcy5zdGF0ZS5maWxlbmFtZSA/PyB0aGlzLmNvbmZpZy5maWxlbmFtZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmRzIHRoZSBsb2cgcXVldWUgcmVjb3JkcyB0byB0aGUgZmlsZVxuICAgKi9cbiAgcHJpdmF0ZSBmbHVzaCgpIHtcbiAgICBjb25zdCB7IHN0YXRlIH0gPSB0aGlzXG4gICAgcmV0dXJuIEZ1dHVyZS5kbyhhc3luYyAoKSA9PiB7XG4gICAgICBzdGF0ZS5mbHVzaGluZyA9IHRydWVcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHsgZmlsZSB9ID0gdGhpc1xuICAgICAgICBpZiAoIWZpbGUpIHtcbiAgICAgICAgICB0aHJvdyBFcnJvcihgJHt0aGlzLmZpbGVuYW1lfSB3YXMgbm90IG9wZW5lZCBwcm9wZXJseWApXG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKHRoaXMucXVldWUubGVuZ3RoKSB7XG4gICAgICAgICAgY29uc3QgYnVmOiBCdWZmZXIgPSB0aGlzLnF1ZXVlLnNoaWZ0KClcblxuICAgICAgICAgIGF3YWl0IEJsdWViaXJkLmZyb21DYWxsYmFjayhjYiA9PlxuICAgICAgICAgICAgRnMuYXBwZW5kRmlsZShmaWxlLCBidWYsIFwidXRmLThcIiwgY2IpXG4gICAgICAgICAgKVxuXG4gICAgICAgICAgc3RhdGUuY3VycmVudFNpemUgKz0gYnVmLmJ5dGVMZW5ndGhcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgbWF4U2l6ZSB9ID0gdGhpcy5jb25maWdcbiAgICAgICAgaWYgKG1heFNpemUgPiAwICYmIHN0YXRlLmN1cnJlbnRTaXplID49IG1heFNpemUpIHtcbiAgICAgICAgICB0aGlzLnJvbGxGaWxlKClcbiAgICAgICAgfVxuXG4gICAgICAgIC8vYXdhaXQgQmx1ZWJpcmQuZnJvbUNhbGxiYWNrKChjYikgPT4gRnMuZmRhdGFzeW5jKHRoaXMuZmlsZSwgY2IpKVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYEZhaWxlZCB0byBhcHBlbmQgZmlsZSAke3RoaXMuZmlsZW5hbWV9YCwgZXJyKVxuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgdGhpcy5zdGF0ZS5mbHVzaGluZyA9IGZhbHNlXG4gICAgICAgIGlmICh0aGlzLnF1ZXVlLmxlbmd0aCkge1xuICAgICAgICAgIHF1ZXVlTWljcm90YXNrKCgpID0+IHRoaXMuZmx1c2goKSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIGxvZyByZWNvcmRzLCB0cmFuc2Zvcm0sIHB1c2ggdG8gRVNcbiAgICpcbiAgICogQHBhcmFtIHJlY29yZFxuICAgKi9cbiAgYXBwZW5kKHJlY29yZDogUmVjb3JkKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgcXVldWUsIGZpbGVuYW1lIH0gPSB0aGlzLnN0YXRlXG4gICAgICBjb25zdCBjb3VudCA9IHF1ZXVlLmxlbmd0aFxuICAgICAgaWYgKGNvdW50ID4gOTk5KSB7XG4gICAgICAgIGRlYnVnKFxuICAgICAgICAgIGBUb28gbWFueSBsb2cgcmVjb3JkcyAoJHtjb3VudH0pIGFyZSBpbiB0aGUgcXVldWUgd2l0aG91dCB0aGUgZmlsZSAoJHtmaWxlbmFtZX0pIG9wZW5pbmcsIHNraXBwaW5nICVPYCxcbiAgICAgICAgICByZWNvcmRcbiAgICAgICAgKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgY29uc3QgZGF0YSA9IHRoaXMuY29uZmlnLnByZXR0eVByaW50XG4gICAgICAgID8gSlNPTi5zdHJpbmdpZnkocmVjb3JkLCBudWxsLCAyKVxuICAgICAgICA6IEpTT04uc3RyaW5naWZ5KHJlY29yZClcbiAgICAgIHF1ZXVlLnB1c2goQnVmZmVyLmZyb20oZGF0YSArIFwiXFxuXCIsIFwidXRmLThcIikpXG4gICAgICB0aGlzLmZsdXNoKClcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUud2FybihgRmFpbGVkIHRvIHN5bmNocm9uaXplIGAsIGVycilcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIHtQYXJ0aWFsPEZpbGVBcHBlbmRlck9wdGlvbnM8UmVjb3JkPj59IG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFBhcnRpYWw8RmlsZUFwcGVuZGVyT3B0aW9uczxSZWNvcmQ+PiA9IHt9KSB7XG4gICAgdGhpcy5jb25maWcgPSBhcHBseUNvbmZpZ0RlZmF1bHRzKG9wdGlvbnMpXG5cbiAgICBhc3NpZ24odGhpcy5zdGF0ZSwge1xuICAgICAgZmlsZW5hbWU6IHRoaXMuY29uZmlnLmZpbGVuYW1lXG4gICAgfSlcblxuICAgIHRoaXMuc2V0dXAoKVxuICAgIGRlYnVnKGBGaWxlIGFwcGVuZGVyIGlzIHJlYWR5LCBsb2dnaW5nIHRvICR7dGhpcy5zdGF0ZS5maWxlbmFtZX1gKVxuICAgIC8vICAgICAgcmV0dXJuIHRoaXNcbiAgfVxufVxuIl19
@@ -1 +0,0 @@
1
- {"version":3,"file":"FileAppender.d.ts","sourceRoot":"","sources":["../../../../src/logging/appenders/FileAppender.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAsB/B,MAAM,WAAW,kBAAkB,CAAC,MAAM,SAAS,SAAS,GAAG,GAAG;IAChE,QAAQ,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf,aAAa,EAAE,OAAO,CAAA;IACtB,WAAW,EAAE,OAAO,CAAA;IACpB,IAAI,EAAE,OAAO,CAAA;CACd;AAED,MAAM,MAAM,mBAAmB,CAAC,MAAM,SAAS,SAAS,GAAG,GAAG,IAAI,OAAO,CACvE,kBAAkB,CAAC,MAAM,CAAC,CAC3B,CAAA;AAED,qBAAa,YAAY,CACvB,MAAM,SAAS,SAAS,CACxB,YAAW,QAAQ,CAAC,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAA;IAE3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAiBrB;IAED,IAAI,aAAa,YAEhB;IAED,OAAO;IAIP;;;;OAIG;IACH,KAAK,IAAI,YAAY,CAAC,MAAM,CAAC;IA2B7B;;;;;;;OAOG;IACH,QAAQ;IAkDR;;;;OAIG;IACH,KAAK;IAML,IAAI,KAAK,8BAER;IAED,IAAI,IAAI,WAEP;IAED,IAAI,QAAQ,YAEX;IAED,IAAI,QAAQ,WAEX;IAED;;OAEG;IACH,OAAO,CAAC,KAAK;IAoCb;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAsB5B;;;OAGG;gBACS,OAAO,GAAE,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAM;CAW/D"}
@@ -1,214 +0,0 @@
1
- import { assign, defaults, padStart } from "lodash";
2
- import * as Path from "path";
3
- import * as Fs from "fs";
4
- import { Option, Future } from "@3fv/prelude-ts";
5
- import { Buffer } from "buffer";
6
- import Debug from "debug";
7
- import Bluebird from "bluebird";
8
- const FsAsync = Fs.promises;
9
- const debug = Debug("3fv:logger:FileAppender");
10
- const osTempDir = process.env.TMP ?? process.env.TEMP ?? "/tmp";
11
- const tempDir = Fs.mkdtempSync(Path.join(osTempDir, "logger-proxy-example")); //
12
- const getDefaultConfig = () => ({
13
- filename: Path.join(tempDir, "app.log"),
14
- prettyPrint: process.env.NODE_ENV !== "production",
15
- maxSize: -1,
16
- maxFiles: 5,
17
- enableRolling: false,
18
- sync: false
19
- });
20
- function applyConfigDefaults(options) {
21
- return defaults(options, getDefaultConfig());
22
- }
23
- export class FileAppender {
24
- config;
25
- state = {
26
- archivedFilenames: [],
27
- filename: undefined,
28
- file: undefined,
29
- ready: false,
30
- currentSize: 0,
31
- flushing: false,
32
- queue: []
33
- };
34
- get enableRolling() {
35
- return this.config.enableRolling;
36
- }
37
- isReady() {
38
- return this.state.ready;
39
- }
40
- /**
41
- * Initialize and setup the appender
42
- *
43
- * @returns {FileAppender<Record>}
44
- */
45
- setup() {
46
- const { state } = this;
47
- if (!!state.ready) {
48
- return this;
49
- }
50
- try {
51
- const { filename } = this;
52
- const file = Fs.openSync(filename, "a");
53
- assign(state, {
54
- filename,
55
- file,
56
- ready: true
57
- });
58
- return this;
59
- }
60
- catch (err) {
61
- assign(state, {
62
- error: err,
63
- file: undefined,
64
- ready: false
65
- });
66
- throw err;
67
- }
68
- }
69
- /**
70
- * Only exposed for the sake of tests & examples
71
- * DO NOT USE
72
- *
73
- * This should all be async, but i was in a rush :(
74
- *
75
- * @returns
76
- */
77
- rollFile() {
78
- const { state, config } = this;
79
- let { file, filename, archivedFilenames } = state;
80
- if (!this.isReady() || !file) {
81
- debug(`Can not roll file before ready`);
82
- return;
83
- }
84
- if (!this.enableRolling) {
85
- return;
86
- }
87
- const fileCount = archivedFilenames.length + 1;
88
- if (config.maxFiles < 1 || fileCount < config.maxFiles) {
89
- archivedFilenames.push(filename + "." + padStart(fileCount.toString(10), 4, "0"));
90
- }
91
- Fs.fdatasyncSync(file);
92
- Fs.closeSync(file);
93
- file = state.file = undefined;
94
- const filenames = [filename, ...archivedFilenames];
95
- let dest = filenames.pop();
96
- while (filenames.length) {
97
- let src = filenames.pop();
98
- if (!Fs.existsSync(src)) {
99
- debug(`src does not exist, skipping ${src}`);
100
- }
101
- else {
102
- debug(`Moving src (${src}) to dest (${dest})`);
103
- if (Fs.existsSync(dest)) {
104
- Fs.unlinkSync(dest);
105
- }
106
- Fs.renameSync(src, dest);
107
- // if (src === filename) {
108
- // Fs.copyFileSync(src, dest)
109
- // Fs.truncateSync(src, 0)
110
- // } else {
111
- // Fs.renameSync(src, dest)
112
- // }
113
- }
114
- dest = src;
115
- }
116
- assign(state, {
117
- currentSize: 0,
118
- file: Fs.openSync(filename, "a")
119
- });
120
- }
121
- /**
122
- * Close the handler
123
- *
124
- * @returns {Promise<void>}
125
- */
126
- close() {
127
- return this.flush()
128
- .onComplete(() => Option.of(this.state.file).map(Fs.closeSync))
129
- .toPromise();
130
- }
131
- get queue() {
132
- return this.state.queue;
133
- }
134
- get file() {
135
- return this.state.file;
136
- }
137
- get flushing() {
138
- return this.state.flushing;
139
- }
140
- get filename() {
141
- return (this.state.filename = this.state.filename ?? this.config.filename);
142
- }
143
- /**
144
- * Appends the log queue records to the file
145
- */
146
- flush() {
147
- const { state } = this;
148
- return Future.do(async () => {
149
- state.flushing = true;
150
- try {
151
- const { file } = this;
152
- if (!file) {
153
- throw Error(`${this.filename} was not opened properly`);
154
- }
155
- while (this.queue.length) {
156
- const buf = this.queue.shift();
157
- await Bluebird.fromCallback(cb => Fs.appendFile(file, buf, "utf-8", cb));
158
- state.currentSize += buf.byteLength;
159
- }
160
- const { maxSize } = this.config;
161
- if (maxSize > 0 && state.currentSize >= maxSize) {
162
- this.rollFile();
163
- }
164
- //await Bluebird.fromCallback((cb) => Fs.fdatasync(this.file, cb))
165
- }
166
- catch (err) {
167
- console.error(`Failed to append file ${this.filename}`, err);
168
- }
169
- finally {
170
- this.state.flushing = false;
171
- if (this.queue.length) {
172
- queueMicrotask(() => this.flush());
173
- }
174
- }
175
- });
176
- }
177
- /**
178
- * Handle log records, transform, push to ES
179
- *
180
- * @param record
181
- */
182
- append(record) {
183
- try {
184
- const { queue, filename } = this.state;
185
- const count = queue.length;
186
- if (count > 999) {
187
- debug(`Too many log records (${count}) are in the queue without the file (${filename}) opening, skipping %O`, record);
188
- return;
189
- }
190
- const data = this.config.prettyPrint
191
- ? JSON.stringify(record, null, 2)
192
- : JSON.stringify(record);
193
- queue.push(Buffer.from(data + "\n", "utf-8"));
194
- this.flush();
195
- }
196
- catch (err) {
197
- console.warn(`Failed to synchronize `, err);
198
- }
199
- }
200
- /**
201
- *
202
- * @param {Partial<FileAppenderOptions<Record>>} options
203
- */
204
- constructor(options = {}) {
205
- this.config = applyConfigDefaults(options);
206
- assign(this.state, {
207
- filename: this.config.filename
208
- });
209
- this.setup();
210
- debug(`File appender is ready, logging to ${this.state.filename}`);
211
- // return this
212
- }
213
- }
214
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlsZUFwcGVuZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xvZ2dpbmcvYXBwZW5kZXJzL0ZpbGVBcHBlbmRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxRQUFRLENBQUE7QUFDbkQsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUE7QUFDNUIsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUE7QUFHeEIsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUNoRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sUUFBUSxDQUFBO0FBQy9CLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQTtBQUN6QixPQUFPLFFBQVEsTUFBTSxVQUFVLENBQUE7QUFFL0IsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQTtBQUUzQixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQTtBQUM5QyxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxNQUFNLENBQUE7QUFDL0QsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxzQkFBc0IsQ0FBQyxDQUFDLENBQUEsQ0FBQyxFQUFFO0FBQy9FLE1BQU0sZ0JBQWdCLEdBQUcsR0FBdUIsRUFBRSxDQUFDLENBQUM7SUFDbEQsUUFBUSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQztJQUN2QyxXQUFXLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEtBQUssWUFBWTtJQUNsRCxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ1gsUUFBUSxF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QUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUNqQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUMxQixLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFBO1lBQzdDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNkLENBQUM7UUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2IsT0FBTyxDQUFDLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxHQUFHLENBQUMsQ0FBQTtRQUM3QyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILFlBQVksVUFBZ0QsRUFBRTtRQUM1RCxJQUFJLENBQUMsTUFBTSxHQUFHLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBRTFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ2pCLFFBQVEsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVE7U0FDL0IsQ0FBQyxDQUFBO1FBRUYsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ1osS0FBSyxDQUFDLHNDQUFzQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUE7UUFDbEUsbUJBQW1CO0lBQ3JCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGFzc2lnbiwgZGVmYXVsdHMsIHBhZFN0YXJ0IH0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQgKiBhcyBQYXRoIGZyb20gXCJwYXRoXCJcbmltcG9ydCAqIGFzIEZzIGZyb20gXCJmc1wiXG5pbXBvcnQgdHlwZSB7IExvZ1JlY29yZCB9IGZyb20gXCIuLi9Mb2dSZWNvcmRcIlxuaW1wb3J0IHR5cGUgeyBBcHBlbmRlciB9IGZyb20gXCIuLi9BcHBlbmRlclwiXG5pbXBvcnQgeyBPcHRpb24sIEZ1dHVyZSB9IGZyb20gXCJAM2Z2L3ByZWx1ZGUtdHNcIlxuaW1wb3J0IHsgQnVmZmVyIH0gZnJvbSBcImJ1ZmZlclwiXG5pbXBvcnQgRGVidWcgZnJvbSBcImRlYnVnXCJcbmltcG9ydCBCbHVlYmlyZCBmcm9tIFwiYmx1ZWJpcmRcIlxuXG5jb25zdCBGc0FzeW5jID0gRnMucHJvbWlzZXNcblxuY29uc3QgZGVidWcgPSBEZWJ1ZyhcIjNmdjpsb2dnZXI6RmlsZUFwcGVuZGVyXCIpXG5jb25zdCBvc1RlbXBEaXIgPSBwcm9jZXNzLmVudi5UTVAgPz8gcHJvY2Vzcy5lbnYuVEVNUCA/PyBcIi90bXBcIlxuY29uc3QgdGVtcERpciA9IEZzLm1rZHRlbXBTeW5jKFBhdGguam9pbihvc1RlbXBEaXIsIFwibG9nZ2VyLXByb3h5LWV4YW1wbGVcIikpIC8vXG5jb25zdCBnZXREZWZhdWx0Q29uZmlnID0gKCk6IEZpbGVBcHBlbmRlckNvbmZpZyA9PiAoe1xuICBmaWxlbmFtZTogUGF0aC5qb2luKHRlbXBEaXIsIFwiYXBwLmxvZ1wiKSxcbiAgcHJldHR5UHJpbnQ6IHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSBcInByb2R1Y3Rpb25cIixcbiAgbWF4U2l6ZTogLTEsXG4gIG1heEZpbGVzOiA1LFxuICBlbmFibGVSb2xsaW5nOiBmYWxzZSxcbiAgc3luYzogZmFsc2Vcbn0pXG5cbmZ1bmN0aW9uIGFwcGx5Q29uZmlnRGVmYXVsdHMob3B0aW9uczogRmlsZUFwcGVuZGVyT3B0aW9ucyk6IEZpbGVBcHBlbmRlckNvbmZpZyB7XG4gIHJldHVybiBkZWZhdWx0cyhvcHRpb25zLCBnZXREZWZhdWx0Q29uZmlnKCkpXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmlsZUFwcGVuZGVyQ29uZmlnPFJlY29yZCBleHRlbmRzIExvZ1JlY29yZCA9IGFueT4ge1xuICBmaWxlbmFtZTogc3RyaW5nXG5cbiAgLyoqXG4gICAqIEZvciByb2xsaW5nXG4gICAqL1xuICBtYXhGaWxlczogbnVtYmVyXG5cbiAgLyoqXG4gICAqIEZvciByb2xsaW5nXG4gICAqL1xuICBtYXhTaXplOiBudW1iZXJcblxuICBlbmFibGVSb2xsaW5nOiBib29sZWFuXG4gIHByZXR0eVByaW50OiBib29sZWFuXG4gIHN5bmM6IGJvb2xlYW5cbn1cblxuZXhwb3J0IHR5cGUgRmlsZUFwcGVuZGVyT3B0aW9uczxSZWNvcmQgZXh0ZW5kcyBMb2dSZWNvcmQgPSBhbnk+ID0gUGFydGlhbDxcbiAgRmlsZUFwcGVuZGVyQ29uZmlnPFJlY29yZD5cbj5cblxuZXhwb3J0IGNsYXNzIEZpbGVBcHBlbmRlcjxcbiAgUmVjb3JkIGV4dGVuZHMgTG9nUmVjb3JkXG4+IGltcGxlbWVudHMgQXBwZW5kZXI8UmVjb3JkPiB7XG4gIHJlYWRvbmx5IGNvbmZpZzogRmlsZUFwcGVuZGVyQ29uZmlnPFJlY29yZD5cblxuICBwcml2YXRlIHJlYWRvbmx5IHN0YXRlOiB7XG4gICAgZmlsZW5hbWU6IHN0cmluZ1xuICAgIGZpbGU6IG51bWJlclxuICAgIGZsdXNoaW5nOiBib29sZWFuXG4gICAgcXVldWU6IEFycmF5PEJ1ZmZlcj5cbiAgICByZWFkeTogYm9vbGVhblxuICAgIGVycm9yPzogRXJyb3JcbiAgICBjdXJyZW50U2l6ZTogbnVtYmVyXG4gICAgYXJjaGl2ZWRGaWxlbmFtZXM6IHN0cmluZ1tdXG4gIH0gPSB7XG4gICAgYXJjaGl2ZWRGaWxlbmFtZXM6IFtdLFxuICAgIGZpbGVuYW1lOiB1bmRlZmluZWQsXG4gICAgZmlsZTogdW5kZWZpbmVkLFxuICAgIHJlYWR5OiBmYWxzZSxcbiAgICBjdXJyZW50U2l6ZTogMCxcbiAgICBmbHVzaGluZzogZmFsc2UsXG4gICAgcXVldWU6IFtdXG4gIH1cblxuICBnZXQgZW5hYmxlUm9sbGluZygpIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZW5hYmxlUm9sbGluZ1xuICB9XG5cbiAgaXNSZWFkeSgpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5yZWFkeVxuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgYW5kIHNldHVwIHRoZSBhcHBlbmRlclxuICAgKlxuICAgKiBAcmV0dXJucyB7RmlsZUFwcGVuZGVyPFJlY29yZD59XG4gICAqL1xuICBzZXR1cCgpOiBGaWxlQXBwZW5kZXI8UmVjb3JkPiB7XG4gICAgY29uc3QgeyBzdGF0ZSB9ID0gdGhpc1xuICAgIGlmICghIXN0YXRlLnJlYWR5KSB7XG4gICAgICByZXR1cm4gdGhpc1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IGZpbGVuYW1lIH0gPSB0aGlzXG4gICAgICBjb25zdCBmaWxlID0gRnMub3BlblN5bmMoZmlsZW5hbWUsIFwiYVwiKVxuXG4gICAgICBhc3NpZ24oc3RhdGUsIHtcbiAgICAgICAgZmlsZW5hbWUsXG4gICAgICAgIGZpbGUsXG4gICAgICAgIHJlYWR5OiB0cnVlXG4gICAgICB9KVxuXG4gICAgICByZXR1cm4gdGhpc1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgYXNzaWduKHN0YXRlLCB7XG4gICAgICAgIGVycm9yOiBlcnIsXG4gICAgICAgIGZpbGU6IHVuZGVmaW5lZCxcbiAgICAgICAgcmVhZHk6IGZhbHNlXG4gICAgICB9KVxuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE9ubHkgZXhwb3NlZCBmb3IgdGhlIHNha2Ugb2YgdGVzdHMgJiBleGFtcGxlc1xuICAgKiBETyBOT1QgVVNFXG4gICAqXG4gICAqIFRoaXMgc2hvdWxkIGFsbCBiZSBhc3luYywgYnV0IGkgd2FzIGluIGEgcnVzaCA6KFxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgcm9sbEZpbGUoKSB7XG4gICAgY29uc3QgeyBzdGF0ZSwgY29uZmlnIH0gPSB0aGlzXG4gICAgbGV0IHsgZmlsZSwgZmlsZW5hbWUsIGFyY2hpdmVkRmlsZW5hbWVzIH0gPSBzdGF0ZVxuICAgIGlmICghdGhpcy5pc1JlYWR5KCkgfHwgIWZpbGUpIHtcbiAgICAgIGRlYnVnKGBDYW4gbm90IHJvbGwgZmlsZSBiZWZvcmUgcmVhZHlgKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmVuYWJsZVJvbGxpbmcpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IGZpbGVDb3VudCA9IGFyY2hpdmVkRmlsZW5hbWVzLmxlbmd0aCArIDFcbiAgICBpZiAoY29uZmlnLm1heEZpbGVzIDwgMSB8fCBmaWxlQ291bnQgPCBjb25maWcubWF4RmlsZXMpIHtcbiAgICAgIGFyY2hpdmVkRmlsZW5hbWVzLnB1c2goXG4gICAgICAgIGZpbGVuYW1lICsgXCIuXCIgKyBwYWRTdGFydChmaWxlQ291bnQudG9TdHJpbmcoMTApLCA0LCBcIjBcIilcbiAgICAgIClcbiAgICB9XG4gICAgRnMuZmRhdGFzeW5jU3luYyhmaWxlKVxuICAgIEZzLmNsb3NlU3luYyhmaWxlKVxuICAgIGZpbGUgPSBzdGF0ZS5maWxlID0gdW5kZWZpbmVkXG4gICAgY29uc3QgZmlsZW5hbWVzID0gW2ZpbGVuYW1lLCAuLi5hcmNoaXZlZEZpbGVuYW1lc11cblxuICAgIGxldCBkZXN0OiBzdHJpbmcgPSBmaWxlbmFtZXMucG9wKClcbiAgICB3aGlsZSAoZmlsZW5hbWVzLmxlbmd0aCkge1xuICAgICAgbGV0IHNyYyA9IGZpbGVuYW1lcy5wb3AoKVxuICAgICAgaWYgKCFGcy5leGlzdHNTeW5jKHNyYykpIHtcbiAgICAgICAgZGVidWcoYHNyYyBkb2VzIG5vdCBleGlzdCwgc2tpcHBpbmcgJHtzcmN9YClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlYnVnKGBNb3Zpbmcgc3JjICgke3NyY30pIHRvIGRlc3QgKCR7ZGVzdH0pYClcbiAgICAgICAgaWYgKEZzLmV4aXN0c1N5bmMoZGVzdCkpIHtcbiAgICAgICAgICBGcy51bmxpbmtTeW5jKGRlc3QpXG4gICAgICAgIH1cbiAgICAgICAgRnMucmVuYW1lU3luYyhzcmMsIGRlc3QpXG4gICAgICAgIC8vIGlmIChzcmMgPT09IGZpbGVuYW1lKSB7XG4gICAgICAgIC8vICAgRnMuY29weUZpbGVTeW5jKHNyYywgZGVzdClcbiAgICAgICAgLy8gICBGcy50cnVuY2F0ZVN5bmMoc3JjLCAwKVxuICAgICAgICAvLyB9IGVsc2Uge1xuICAgICAgICAvLyAgIEZzLnJlbmFtZVN5bmMoc3JjLCBkZXN0KVxuICAgICAgICAvLyB9XG4gICAgICB9XG4gICAgICBkZXN0ID0gc3JjXG4gICAgfVxuXG4gICAgYXNzaWduKHN0YXRlLCB7XG4gICAgICBjdXJyZW50U2l6ZTogMCxcbiAgICAgIGZpbGU6IEZzLm9wZW5TeW5jKGZpbGVuYW1lLCBcImFcIilcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIHRoZSBoYW5kbGVyXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmx1c2goKVxuICAgICAgLm9uQ29tcGxldGUoKCkgPT4gT3B0aW9uLm9mKHRoaXMuc3RhdGUuZmlsZSkubWFwKEZzLmNsb3NlU3luYykpXG4gICAgICAudG9Qcm9taXNlKClcbiAgfVxuXG4gIGdldCBxdWV1ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5xdWV1ZVxuICB9XG5cbiAgZ2V0IGZpbGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGUuZmlsZVxuICB9XG5cbiAgZ2V0IGZsdXNoaW5nKCkge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLmZsdXNoaW5nXG4gIH1cblxuICBnZXQgZmlsZW5hbWUoKSB7XG4gICAgcmV0dXJuICh0aGlzLnN0YXRlLmZpbGVuYW1lID0gdGhpcy5zdGF0ZS5maWxlbmFtZSA/PyB0aGlzLmNvbmZpZy5maWxlbmFtZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmRzIHRoZSBsb2cgcXVldWUgcmVjb3JkcyB0byB0aGUgZmlsZVxuICAgKi9cbiAgcHJpdmF0ZSBmbHVzaCgpIHtcbiAgICBjb25zdCB7IHN0YXRlIH0gPSB0aGlzXG4gICAgcmV0dXJuIEZ1dHVyZS5kbyhhc3luYyAoKSA9PiB7XG4gICAgICBzdGF0ZS5mbHVzaGluZyA9IHRydWVcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHsgZmlsZSB9ID0gdGhpc1xuICAgICAgICBpZiAoIWZpbGUpIHtcbiAgICAgICAgICB0aHJvdyBFcnJvcihgJHt0aGlzLmZpbGVuYW1lfSB3YXMgbm90IG9wZW5lZCBwcm9wZXJseWApXG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKHRoaXMucXVldWUubGVuZ3RoKSB7XG4gICAgICAgICAgY29uc3QgYnVmOiBCdWZmZXIgPSB0aGlzLnF1ZXVlLnNoaWZ0KClcblxuICAgICAgICAgIGF3YWl0IEJsdWViaXJkLmZyb21DYWxsYmFjayhjYiA9PlxuICAgICAgICAgICAgRnMuYXBwZW5kRmlsZShmaWxlLCBidWYsIFwidXRmLThcIiwgY2IpXG4gICAgICAgICAgKVxuXG4gICAgICAgICAgc3RhdGUuY3VycmVudFNpemUgKz0gYnVmLmJ5dGVMZW5ndGhcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgbWF4U2l6ZSB9ID0gdGhpcy5jb25maWdcbiAgICAgICAgaWYgKG1heFNpemUgPiAwICYmIHN0YXRlLmN1cnJlbnRTaXplID49IG1heFNpemUpIHtcbiAgICAgICAgICB0aGlzLnJvbGxGaWxlKClcbiAgICAgICAgfVxuXG4gICAgICAgIC8vYXdhaXQgQmx1ZWJpcmQuZnJvbUNhbGxiYWNrKChjYikgPT4gRnMuZmRhdGFzeW5jKHRoaXMuZmlsZSwgY2IpKVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYEZhaWxlZCB0byBhcHBlbmQgZmlsZSAke3RoaXMuZmlsZW5hbWV9YCwgZXJyKVxuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgdGhpcy5zdGF0ZS5mbHVzaGluZyA9IGZhbHNlXG4gICAgICAgIGlmICh0aGlzLnF1ZXVlLmxlbmd0aCkge1xuICAgICAgICAgIHF1ZXVlTWljcm90YXNrKCgpID0+IHRoaXMuZmx1c2goKSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIGxvZyByZWNvcmRzLCB0cmFuc2Zvcm0sIHB1c2ggdG8gRVNcbiAgICpcbiAgICogQHBhcmFtIHJlY29yZFxuICAgKi9cbiAgYXBwZW5kKHJlY29yZDogUmVjb3JkKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgcXVldWUsIGZpbGVuYW1lIH0gPSB0aGlzLnN0YXRlXG4gICAgICBjb25zdCBjb3VudCA9IHF1ZXVlLmxlbmd0aFxuICAgICAgaWYgKGNvdW50ID4gOTk5KSB7XG4gICAgICAgIGRlYnVnKFxuICAgICAgICAgIGBUb28gbWFueSBsb2cgcmVjb3JkcyAoJHtjb3VudH0pIGFyZSBpbiB0aGUgcXVldWUgd2l0aG91dCB0aGUgZmlsZSAoJHtmaWxlbmFtZX0pIG9wZW5pbmcsIHNraXBwaW5nICVPYCxcbiAgICAgICAgICByZWNvcmRcbiAgICAgICAgKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgY29uc3QgZGF0YSA9IHRoaXMuY29uZmlnLnByZXR0eVByaW50XG4gICAgICAgID8gSlNPTi5zdHJpbmdpZnkocmVjb3JkLCBudWxsLCAyKVxuICAgICAgICA6IEpTT04uc3RyaW5naWZ5KHJlY29yZClcbiAgICAgIHF1ZXVlLnB1c2goQnVmZmVyLmZyb20oZGF0YSArIFwiXFxuXCIsIFwidXRmLThcIikpXG4gICAgICB0aGlzLmZsdXNoKClcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUud2FybihgRmFpbGVkIHRvIHN5bmNocm9uaXplIGAsIGVycilcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIHtQYXJ0aWFsPEZpbGVBcHBlbmRlck9wdGlvbnM8UmVjb3JkPj59IG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFBhcnRpYWw8RmlsZUFwcGVuZGVyT3B0aW9uczxSZWNvcmQ+PiA9IHt9KSB7XG4gICAgdGhpcy5jb25maWcgPSBhcHBseUNvbmZpZ0RlZmF1bHRzKG9wdGlvbnMpXG5cbiAgICBhc3NpZ24odGhpcy5zdGF0ZSwge1xuICAgICAgZmlsZW5hbWU6IHRoaXMuY29uZmlnLmZpbGVuYW1lXG4gICAgfSlcblxuICAgIHRoaXMuc2V0dXAoKVxuICAgIGRlYnVnKGBGaWxlIGFwcGVuZGVyIGlzIHJlYWR5LCBsb2dnaW5nIHRvICR7dGhpcy5zdGF0ZS5maWxlbmFtZX1gKVxuICAgIC8vICAgICAgcmV0dXJuIHRoaXNcbiAgfVxufVxuIl19