@tryghost/bunyan-rotating-filestream 0.0.7 → 0.0.9

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.
package/LICENSE CHANGED
@@ -1,4 +1,6 @@
1
- Copyright (c) 2013-2021 Ghost Foundation
1
+ MIT License
2
+
3
+ Copyright (c) 2013-2026 Ghost Foundation
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
6
  of this software and associated documentation files (the "Software"), to deal
@@ -17,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
21
  SOFTWARE.
20
-
package/README.md CHANGED
@@ -6,51 +6,59 @@
6
6
 
7
7
  or
8
8
 
9
- `yarn add @tryghost/bunyan-rotating-filestream`
9
+ `pnpm add @tryghost/bunyan-rotating-filestream`
10
10
 
11
+ ## Purpose
12
+
13
+ A rotating file stream for the [bunyan](https://github.com/trentm/node-bunyan) logger, supporting period-based and size-based rotation, gzip compression of archives, and limits on the number and total size of archived files.
11
14
 
12
15
  ## Usage
13
16
 
14
17
  Create a bunyan logger using the stream:
15
18
 
16
19
  ```js
17
- var log = bunyan.createLogger({
18
- name: 'foo',
19
- streams: [{
20
+ const log = bunyan.createLogger({
21
+ name: 'foo',
22
+ streams: [
23
+ {
20
24
  stream: new RotatingFileStream({
21
25
  path: '/var/log/foo.log',
22
- period: '1d', // daily rotation
23
- totalFiles: 10, // keep up to 10 backup copies
24
- rotateExisting: true, // Give ourselves a clean file when we start up, based on period
25
- threshold: '10m', // Rotate log files larger than 10 megabytes
26
- totalSize: '20m', // Don't keep more than 20mb of archived log files
27
- gzip: true // Compress the archive log files to save space
28
- })
29
- }]
30
- });
26
+ period: '1d', // daily rotation
27
+ totalFiles: 10, // keep up to 10 backup copies
28
+ rotateExisting: true, // Give ourselves a clean file when we start up, based on period
29
+ threshold: '10m', // Rotate log files larger than 10 megabytes
30
+ totalSize: '20m', // Don't keep more than 20mb of archived log files
31
+ gzip: true, // Compress the archive log files to save space
32
+ }),
33
+ },
34
+ ],
35
+ });
31
36
  ```
32
37
 
33
38
  Other options include `startNewFile` to always open a new file on start-up.
34
39
 
35
40
  ## Develop
36
41
 
37
- 1. `git clone` this repo & `cd` into it as usual
38
- 2. Run `yarn` to install top-level dependencies.
42
+ This is a mono repository, managed with [Nx](https://nx.dev).
39
43
 
40
- ## Test
44
+ Follow the instructions for the top-level repo.
41
45
 
42
- - `yarn lint` run just eslint
43
- - `yarn test` run lint and tests
46
+ 1. `git clone` this repo & `cd` into it as usual
47
+ 2. Run `pnpm install` to install top-level dependencies.
48
+
49
+ ## Run
44
50
 
51
+ - `pnpm dev`
45
52
 
46
- ## Publish
53
+ ## Test
47
54
 
48
- - `yarn ship`
55
+ - `pnpm lint` runs oxlint
56
+ - `pnpm test` runs lint and tests
49
57
 
50
58
  ## Credit
51
59
 
52
60
  Many thanks to @Rcomian for their work on the original bunyan-rotating-file-stream project, this project borrows lots of the code and all of the ideas in the original.
53
61
 
54
- # Copyright & License
62
+ # Copyright & License
55
63
 
56
- Copyright (c) 2013-2021 Ghost Foundation - Released under the [MIT license](LICENSE).
64
+ Copyright (c) 2013-2026 Ghost Foundation - Released under the [MIT license](LICENSE).
package/index.js CHANGED
@@ -2,7 +2,7 @@ const WriteQueue = require('./lib/writeQueue');
2
2
  const PeriodTrigger = require('./lib/periodTrigger');
3
3
  const ThresholdTrigger = require('./lib/thresholdTrigger');
4
4
  const FileRotator = require('./lib/fileRotator');
5
- const {BytesWritten, Rotate, NewFile} = require('./lib/customEvents');
5
+ const { BytesWritten, Rotate, NewFile } = require('./lib/customEvents');
6
6
 
7
7
  const fileStreams = [];
8
8
 
@@ -25,10 +25,11 @@ class RotatingFileStream {
25
25
  }
26
26
  if (config.threshold) {
27
27
  const thresholdTrigger = new ThresholdTrigger(config.threshold);
28
- this._queue.on(BytesWritten, bytes => thresholdTrigger.updateWritten(bytes));
28
+ this._queue.on(BytesWritten, (bytes) => thresholdTrigger.updateWritten(bytes));
29
29
  this._triggers.push(thresholdTrigger);
30
30
  }
31
31
  this._rotatingLock = false;
32
+ this._closed = false;
32
33
  this._triggers.forEach((trigger) => {
33
34
  trigger.on(Rotate, () => {
34
35
  this._rotate();
@@ -36,21 +37,24 @@ class RotatingFileStream {
36
37
  });
37
38
  this._rotator.on(NewFile, (fileInfo) => {
38
39
  this._queue.setFileHandle(this._rotator.getCurrentHandle());
39
- this._triggers.forEach(trigger => trigger.newFile(fileInfo));
40
+ this._triggers.forEach((trigger) => trigger.newFile(fileInfo));
40
41
  });
41
42
  this._initialised = this._rotator.initialise();
42
43
  }
43
44
 
44
45
  async _rotate() {
45
- if (this._rotatingLock) {
46
- // Already rotating
46
+ if (this._rotatingLock || this._closed) {
47
+ // Already rotating or shutting down
47
48
  return;
48
49
  }
49
50
  this._rotatingLock = true;
50
- await this._queue.pause();
51
- const nextFileHandle = await this._rotator.rotate();
52
- this._queue.setFileHandle(nextFileHandle);
53
- this._rotatingLock = false;
51
+ this._rotating = (async () => {
52
+ await this._queue.pause();
53
+ const nextFileHandle = await this._rotator.rotate();
54
+ this._queue.setFileHandle(nextFileHandle);
55
+ this._rotatingLock = false;
56
+ })();
57
+ await this._rotating;
54
58
  }
55
59
 
56
60
  async write(data) {
@@ -58,10 +62,16 @@ class RotatingFileStream {
58
62
  }
59
63
 
60
64
  async end() {
65
+ // Block new rotations immediately - the threshold trigger has no timer
66
+ // to shut down and can still fire while the queue drains below
67
+ this._closed = true;
61
68
  await this._initialised;
69
+ // Stop triggers first so no new rotation can start, then wait for any
70
+ // in-flight rotation before closing the file handles
71
+ this._triggers.forEach((trigger) => trigger.shutdown());
72
+ await this._rotating;
62
73
  await this._queue.shutdown();
63
74
  await this._rotator.shutdown();
64
- this._triggers.forEach(trigger => trigger.shutdown());
65
75
  const fileStreamIndex = fileStreams.indexOf(this._path);
66
76
  if (fileStreamIndex >= 0) {
67
77
  fileStreams.splice(fileStreamIndex, 1);
@@ -4,5 +4,5 @@ module.exports = {
4
4
  // Emitted when a new file handle is acquired with the file info
5
5
  NewFile: Symbol('newFile'),
6
6
  // Emitted whenever data is written to the file with the number of bytes
7
- BytesWritten: Symbol('bytesWritten')
8
- };
7
+ BytesWritten: Symbol('bytesWritten'),
8
+ };
@@ -1,14 +1,14 @@
1
1
  const zlib = require('zlib');
2
- const {pipeline} = require('stream');
3
- const {promisify} = require('util');
4
- const {createReadStream, createWriteStream} = require('fs');
2
+ const { pipeline } = require('stream');
3
+ const { promisify } = require('util');
4
+ const { createReadStream, createWriteStream } = require('fs');
5
5
  const fs = require('fs').promises;
6
6
  const pipe = promisify(pipeline);
7
7
  const path = require('path');
8
- const {processSize} = require('../util/configProcessors');
8
+ const { processSize } = require('../util/configProcessors');
9
9
 
10
- const {EventEmitter} = require('events');
11
- const {NewFile} = require('./customEvents');
10
+ const { EventEmitter } = require('events');
11
+ const { NewFile } = require('./customEvents');
12
12
 
13
13
  class FileRotator extends EventEmitter {
14
14
  constructor(config) {
@@ -75,7 +75,7 @@ class FileRotator extends EventEmitter {
75
75
  const outputName = this._getFileName(0, true);
76
76
 
77
77
  try {
78
- fs.stat(inputName);
78
+ await fs.stat(inputName);
79
79
  } catch (err) {
80
80
  if (err.code === 'ENOENT') {
81
81
  return;
@@ -97,11 +97,12 @@ class FileRotator extends EventEmitter {
97
97
  const parsedPath = path.parse(this._path);
98
98
  let base = `${parsedPath.name}.${String(number - 1)}${parsedPath.ext}`;
99
99
  if (number === 0) {
100
- base = parsedPath.name
101
- .replace('.%N', '')
102
- .replace('_%N', '')
103
- .replace('-%N', '')
104
- .replace('%N', '') + parsedPath.ext;
100
+ base =
101
+ parsedPath.name
102
+ .replace('.%N', '')
103
+ .replace('_%N', '')
104
+ .replace('-%N', '')
105
+ .replace('%N', '') + parsedPath.ext;
105
106
  } else if (parsedPath.name.indexOf('%N') >= 0) {
106
107
  base = parsedPath.name.replace('%N', String(number - 1)) + parsedPath.ext;
107
108
  }
@@ -124,7 +125,10 @@ class FileRotator extends EventEmitter {
124
125
  try {
125
126
  const result = await fs.stat(name);
126
127
  bytesTotal += result.size;
127
- if ((this._totalSize && bytesTotal > this._totalSize) || (this._totalFiles && fileNumber >= this._totalFiles)) {
128
+ if (
129
+ (this._totalSize && bytesTotal > this._totalSize) ||
130
+ (this._totalFiles && fileNumber >= this._totalFiles)
131
+ ) {
128
132
  filesToDelete.push(name);
129
133
  }
130
134
  } catch (err) {
@@ -159,7 +163,10 @@ class FileRotator extends EventEmitter {
159
163
  // Set to last file in sequence
160
164
  fileNumber -= 1;
161
165
  while (fileNumber >= 0) {
162
- await fs.rename(this._getFileName(fileNumber, true), this._getFileName(fileNumber + 1, true));
166
+ await fs.rename(
167
+ this._getFileName(fileNumber, true),
168
+ this._getFileName(fileNumber + 1, true),
169
+ );
163
170
  fileNumber -= 1;
164
171
  }
165
172
  }
@@ -173,4 +180,4 @@ class FileRotator extends EventEmitter {
173
180
  }
174
181
  }
175
182
 
176
- module.exports = FileRotator;
183
+ module.exports = FileRotator;
@@ -1,68 +1,77 @@
1
- const {EventEmitter} = require('events');
2
- const {Rotate} = require('./customEvents');
3
- const {processPeriod} = require('../util/configProcessors');
4
- const {setTimeout, clearTimeout} = require('long-timeout');
1
+ const { EventEmitter } = require('events');
2
+ const { Rotate } = require('./customEvents');
3
+ const { processPeriod } = require('../util/configProcessors');
4
+ const { setTimeout, clearTimeout } = require('long-timeout');
5
5
 
6
6
  const getNextRotation = (period, lastRotation) => {
7
7
  var date = new Date();
8
8
 
9
9
  let nextRotation;
10
10
  switch (period.unit) {
11
- case 'ms':
12
- // Hidden millisecond period for debugging.
13
- if (lastRotation) {
14
- nextRotation = lastRotation + period.num;
15
- } else {
16
- nextRotation = Date.now() + period.num;
17
- }
18
- break;
19
- case 'h':
20
- if (lastRotation) {
21
- nextRotation = lastRotation + period.num * 60 * 60 * 1000;
22
- } else {
23
- // First time: top of the next hour.
24
- nextRotation = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(),
25
- date.getUTCDate(), date.getUTCHours() + 1);
26
- }
27
- break;
28
- case 'd':
29
- if (lastRotation) {
30
- nextRotation = lastRotation + period.num * 24 * 60 * 60 * 1000;
31
- } else {
32
- // First time: start of tomorrow (i.e. at the coming midnight) UTC.
33
- nextRotation = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(),
34
- date.getUTCDate() + 1);
35
- }
36
- break;
37
- case 'w':
38
- // Currently, always on Sunday morning at 00:00:00 (UTC).
39
- if (lastRotation) {
40
- nextRotation = lastRotation + period.num * 7 * 24 * 60 * 60 * 1000;
41
- } else {
42
- // First time: this coming Sunday.
43
- nextRotation = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(),
44
- date.getUTCDate() + (7 - date.getUTCDay()));
45
- }
46
- break;
47
- case 'm':
48
- if (lastRotation) {
49
- nextRotation = Date.UTC(date.getUTCFullYear(),
50
- date.getUTCMonth() + period.num, 1);
51
- } else {
52
- // First time: the start of the next month.
53
- nextRotation = Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1);
54
- }
55
- break;
56
- case 'y':
57
- if (lastRotation) {
58
- nextRotation = Date.UTC(date.getUTCFullYear() + period.num, 0, 1);
59
- } else {
60
- // First time: the start of the next year.
61
- nextRotation = Date.UTC(date.getUTCFullYear() + 1, 0, 1);
62
- }
63
- break;
64
- default:
65
- throw new Error(`Invalid period scope: "${period.unit}"`);
11
+ case 'ms':
12
+ // Hidden millisecond period for debugging.
13
+ if (lastRotation) {
14
+ nextRotation = lastRotation + period.num;
15
+ } else {
16
+ nextRotation = Date.now() + period.num;
17
+ }
18
+ break;
19
+ case 'h':
20
+ if (lastRotation) {
21
+ nextRotation = lastRotation + period.num * 60 * 60 * 1000;
22
+ } else {
23
+ // First time: top of the next hour.
24
+ nextRotation = Date.UTC(
25
+ date.getUTCFullYear(),
26
+ date.getUTCMonth(),
27
+ date.getUTCDate(),
28
+ date.getUTCHours() + 1,
29
+ );
30
+ }
31
+ break;
32
+ case 'd':
33
+ if (lastRotation) {
34
+ nextRotation = lastRotation + period.num * 24 * 60 * 60 * 1000;
35
+ } else {
36
+ // First time: start of tomorrow (i.e. at the coming midnight) UTC.
37
+ nextRotation = Date.UTC(
38
+ date.getUTCFullYear(),
39
+ date.getUTCMonth(),
40
+ date.getUTCDate() + 1,
41
+ );
42
+ }
43
+ break;
44
+ case 'w':
45
+ // Currently, always on Sunday morning at 00:00:00 (UTC).
46
+ if (lastRotation) {
47
+ nextRotation = lastRotation + period.num * 7 * 24 * 60 * 60 * 1000;
48
+ } else {
49
+ // First time: this coming Sunday.
50
+ nextRotation = Date.UTC(
51
+ date.getUTCFullYear(),
52
+ date.getUTCMonth(),
53
+ date.getUTCDate() + (7 - date.getUTCDay()),
54
+ );
55
+ }
56
+ break;
57
+ case 'm':
58
+ if (lastRotation) {
59
+ nextRotation = Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + period.num, 1);
60
+ } else {
61
+ // First time: the start of the next month.
62
+ nextRotation = Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1);
63
+ }
64
+ break;
65
+ case 'y':
66
+ if (lastRotation) {
67
+ nextRotation = Date.UTC(date.getUTCFullYear() + period.num, 0, 1);
68
+ } else {
69
+ // First time: the start of the next year.
70
+ nextRotation = Date.UTC(date.getUTCFullYear() + 1, 0, 1);
71
+ }
72
+ break;
73
+ default:
74
+ throw new Error(`Invalid period scope: "${period.unit}"`);
66
75
  }
67
76
 
68
77
  return nextRotation;
@@ -97,10 +106,13 @@ class PeriodTrigger extends EventEmitter {
97
106
  clearTimeout(this._task);
98
107
  }
99
108
  this._rotateAt = getNextRotation(this._period, this._rotateAt);
100
- this._task = setTimeout(() => {
101
- this._emitRotate();
102
- this.setNextTask();
103
- }, Math.max(this._rotateAt - Date.now(), 0));
109
+ this._task = setTimeout(
110
+ () => {
111
+ this._emitRotate();
112
+ this.setNextTask();
113
+ },
114
+ Math.max(this._rotateAt - Date.now(), 0),
115
+ );
104
116
  // Prevent timeout from keeping Node.js alive
105
117
  this._task.unref();
106
118
  }
@@ -110,4 +122,4 @@ class PeriodTrigger extends EventEmitter {
110
122
  }
111
123
  }
112
124
 
113
- module.exports = PeriodTrigger;
125
+ module.exports = PeriodTrigger;
@@ -1,6 +1,6 @@
1
- const {EventEmitter} = require('events');
2
- const {Rotate} = require('./customEvents');
3
- const {processSize} = require('../util/configProcessors');
1
+ const { EventEmitter } = require('events');
2
+ const { Rotate } = require('./customEvents');
3
+ const { processSize } = require('../util/configProcessors');
4
4
 
5
5
  class ThresholdTrigger extends EventEmitter {
6
6
  constructor(threshold) {
@@ -29,4 +29,4 @@ class ThresholdTrigger extends EventEmitter {
29
29
  }
30
30
  }
31
31
 
32
- module.exports = ThresholdTrigger;
32
+ module.exports = ThresholdTrigger;
package/lib/writeQueue.js CHANGED
@@ -1,5 +1,5 @@
1
- const {EventEmitter} = require('events');
2
- const {BytesWritten} = require('./customEvents');
1
+ const { EventEmitter } = require('events');
2
+ const { BytesWritten } = require('./customEvents');
3
3
 
4
4
  class WriteQueue extends EventEmitter {
5
5
  constructor() {
@@ -49,4 +49,4 @@ class WriteQueue extends EventEmitter {
49
49
  }
50
50
  }
51
51
 
52
- module.exports = WriteQueue;
52
+ module.exports = WriteQueue;
package/package.json CHANGED
@@ -1,28 +1,33 @@
1
1
  {
2
2
  "name": "@tryghost/bunyan-rotating-filestream",
3
- "version": "0.0.7",
4
- "repository": "git@github.com:TryGhost/bunyan-rotating-filestream.git",
5
- "author": "Ghost Foundation",
3
+ "version": "0.0.9",
6
4
  "license": "MIT",
7
- "private": false,
5
+ "author": "Ghost Foundation",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/TryGhost/framework.git",
9
+ "directory": "packages/bunyan-rotating-filestream"
10
+ },
11
+ "files": [
12
+ "index.js",
13
+ "lib",
14
+ "util"
15
+ ],
8
16
  "main": "index.js",
9
- "scripts": {
10
- "test": "NODE_ENV=testing mocha './test/**/*.test.js'",
11
- "lint": "eslint . --ext .js --cache",
12
- "posttest": "yarn lint",
13
- "preship": "yarn test",
14
- "ship": "STATUS=$(git status --porcelain); echo $STATUS; if [ -z \"$STATUS\" ]; then yarn publish --access public && git push --follow-tags; fi"
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "dependencies": {
21
+ "long-timeout": "0.1.1"
15
22
  },
16
23
  "devDependencies": {
17
24
  "bunyan": "1.8.15",
18
- "eslint": "7.21.0",
19
- "eslint-plugin-ghost": "2.0.0",
20
- "mkdirp": "1.0.4",
21
- "mocha": "8.3.0",
22
- "should": "13.2.3",
23
- "sinon": "9.2.4"
25
+ "sinon": "22.0.0"
24
26
  },
25
- "dependencies": {
26
- "long-timeout": "^0.1.1"
27
+ "scripts": {
28
+ "dev": "echo \"Implement me!\"",
29
+ "test": "NODE_ENV=testing vitest run --coverage",
30
+ "lint": "oxlint -c ../../.oxlintrc.json .",
31
+ "posttest": "pnpm run lint"
27
32
  }
28
- }
33
+ }
@@ -3,10 +3,10 @@ const processSize = (size) => {
3
3
  b: 1,
4
4
  k: 1024,
5
5
  m: 1024 * 1024,
6
- g: 1024 * 1024 * 1024
6
+ g: 1024 * 1024 * 1024,
7
7
  };
8
-
9
- if (typeof (size) === 'string') {
8
+
9
+ if (typeof size === 'string') {
10
10
  const [num, unit] = /^([1-9][0-9]*)([bkmg])$/.exec(size).slice(1);
11
11
  return Number(num) * multipliers[unit];
12
12
  } else {
@@ -17,21 +17,22 @@ const processSize = (size) => {
17
17
  const processPeriod = (period) => {
18
18
  const result = {
19
19
  num: 1,
20
- unit: 'd'
20
+ unit: 'd',
21
21
  };
22
22
 
23
23
  // Parse `period`.
24
24
  if (period) {
25
- var crackedperiod = {
26
- hourly: '1h',
27
- daily: '1d',
28
- weekly: '1w',
29
- monthly: '1m',
30
- yearly: '1y'
31
- }[period] || period;
25
+ var crackedperiod =
26
+ {
27
+ hourly: '1h',
28
+ daily: '1d',
29
+ weekly: '1w',
30
+ monthly: '1m',
31
+ yearly: '1y',
32
+ }[period] || period;
32
33
 
33
34
  const [num, unit] = /^([1-9][0-9]*)([hdwmy]|ms)$/.exec(crackedperiod).slice(1);
34
-
35
+
35
36
  result.num = Number(num);
36
37
  result.unit = unit;
37
38
  }
@@ -41,5 +42,5 @@ const processPeriod = (period) => {
41
42
 
42
43
  module.exports = {
43
44
  processSize,
44
- processPeriod
45
- };
45
+ processPeriod,
46
+ };
package/.editorconfig DELETED
@@ -1,26 +0,0 @@
1
- # http://editorconfig.org
2
-
3
- root = true
4
-
5
- [*]
6
- charset = utf-8
7
- indent_style = space
8
- indent_size = 4
9
- end_of_line = lf
10
- insert_final_newline = true
11
- trim_trailing_whitespace = true
12
-
13
- [*.hbs]
14
- insert_final_newline = false
15
-
16
- [*.json]
17
- indent_size = 2
18
-
19
- [*.md]
20
- trim_trailing_whitespace = false
21
-
22
- [*.{yml,yaml}]
23
- indent_size = 2
24
-
25
- [Makefile]
26
- indent_style = tab
package/.eslintrc.js DELETED
@@ -1,6 +0,0 @@
1
- module.exports = {
2
- plugins: ['ghost'],
3
- extends: [
4
- 'plugin:ghost/node'
5
- ]
6
- };
@@ -1,23 +0,0 @@
1
- name: Test
2
- on:
3
- pull_request:
4
- push:
5
- branches:
6
- - main
7
- jobs:
8
- build:
9
- runs-on: ubuntu-latest
10
- strategy:
11
- matrix:
12
- node: [ 10, 12 ]
13
- env:
14
- FORCE_COLOR: 1
15
- name: Node ${{ matrix.node }}
16
- steps:
17
- - uses: actions/checkout@v2
18
- - uses: actions/setup-node@v2
19
- with:
20
- node-version: ${{ matrix.node }}
21
-
22
- - run: yarn
23
- - run: yarn test
package/renovate.json DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "extends": [
3
- "config:base"
4
- ]
5
- }
package/test/.eslintrc.js DELETED
@@ -1,6 +0,0 @@
1
- module.exports = {
2
- plugins: ['ghost'],
3
- extends: [
4
- 'plugin:ghost/test'
5
- ]
6
- };
@@ -1,98 +0,0 @@
1
- const sinon = require('sinon');
2
- const assert = require('assert');
3
- const sandbox = sinon.createSandbox();
4
- const bunyan = require('bunyan');
5
- const path = require('path');
6
-
7
- const RotatingFileStream = require('../index');
8
- const fs = require('fs').promises;
9
- const testConfig = {
10
- path: 'logs/foo.log',
11
- totalFiles: 10,
12
- threshold: '1k',
13
- rotateExisting: true,
14
- gzip: true
15
- };
16
-
17
- function delay(ms) {
18
- return new Promise(resolve => setTimeout(resolve, ms));
19
- }
20
-
21
- describe('RotatingFileStream', function () {
22
- before(async function () {
23
- await fs.mkdir(path.parse(testConfig.path).dir, {
24
- recursive: true
25
- });
26
- });
27
-
28
- afterEach(function () {
29
- sandbox.restore();
30
- });
31
-
32
- it('Processes client configuration', async function () {
33
- const rfs = new RotatingFileStream(testConfig);
34
- assert.strictEqual(rfs._path, testConfig.path);
35
- await rfs.end();
36
- });
37
-
38
- it('Writes log files', async function () {
39
- const stream = new RotatingFileStream(testConfig);
40
- const logger = bunyan.createLogger({
41
- name: 'foo',
42
- streams: [{
43
- stream
44
- }]
45
- });
46
- for (let i = 0; i < 100; i++) {
47
- logger.info('Testing ' + i);
48
- }
49
- await delay(0); // immediate delay causes logs to sync
50
- await stream.end();
51
- });
52
-
53
- it('Sets up period correctly', async function () {
54
- const stream = new RotatingFileStream({
55
- period: '1w',
56
- ...testConfig
57
- });
58
- bunyan.createLogger({
59
- name: 'foo',
60
- streams: [{
61
- stream
62
- }]
63
- });
64
- await stream.end();
65
- });
66
-
67
- it('Sets up long periods correctly', async function () {
68
- const stream = new RotatingFileStream({
69
- period: '1y',
70
- ...testConfig
71
- });
72
- bunyan.createLogger({
73
- name: 'foo',
74
- streams: [{
75
- stream
76
- }]
77
- });
78
- await stream.end();
79
- });
80
-
81
- it('Goes fast with short periods', async function () {
82
- const stream = new RotatingFileStream({
83
- period: '50ms',
84
- ...testConfig
85
- });
86
- const logger = bunyan.createLogger({
87
- name: 'foo',
88
- streams: [{
89
- stream
90
- }]
91
- });
92
- for (let i = 0; i < 10; i++) {
93
- logger.info(`Testing ${i}!`);
94
- await delay(50);
95
- }
96
- await stream.end();
97
- });
98
- });
@@ -1,11 +0,0 @@
1
- /**
2
- * Custom Should Assertions
3
- *
4
- * Add any custom assertions to this file.
5
- */
6
-
7
- // Example Assertion
8
- // should.Assertion.add('ExampleAssertion', function () {
9
- // this.params = {operator: 'to be a valid Example Assertion'};
10
- // this.obj.should.be.an.Object;
11
- // });
@@ -1,11 +0,0 @@
1
- /**
2
- * Test Utilities
3
- *
4
- * Shared utils for writing tests
5
- */
6
-
7
- // Require overrides - these add globals for tests
8
- require('./overrides');
9
-
10
- // Require assertions - adds custom should assertions
11
- require('./assertions');
@@ -1,10 +0,0 @@
1
- // This file is required before any test is run
2
-
3
- // Taken from the should wiki, this is how to make should global
4
- // Should is a global in our eslint test config
5
- global.should = require('should').noConflict();
6
- should.extend();
7
-
8
- // Sinon is a simple case
9
- // Sinon is a global in our eslint test config
10
- global.sinon = require('sinon');