@stonyx/logs 1.0.0
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/.eslintrc.cjs +118 -0
- package/.github/FUNDING.yml +1 -0
- package/.github/workflows/ci.yml +16 -0
- package/.github/workflows/publish.yml +51 -0
- package/LICENSE +674 -0
- package/README.md +278 -0
- package/package.json +50 -0
- package/src/color.js +50 -0
- package/src/index.js +172 -0
package/README.md
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<br>
|
|
3
|
+
<br>
|
|
4
|
+
<img width="560" src="https://github.com/abofs/chronicle/raw/master/media/chronicle-logo.svg" alt="Chronicle">
|
|
5
|
+
<br>
|
|
6
|
+
<br>
|
|
7
|
+
<br>
|
|
8
|
+
</h1>
|
|
9
|
+
|
|
10
|
+
> Simplified logging for node applications
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
<br>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<div align="center">
|
|
19
|
+
<p>
|
|
20
|
+
<p>
|
|
21
|
+
<sup>
|
|
22
|
+
If our projects are useful to you, please consider becoming a <a href="https://github.com/sponsors/abofs">GitHub Sponsor</a>
|
|
23
|
+
</sup>
|
|
24
|
+
</p>
|
|
25
|
+
</p>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
**Chronicle** is built on top of all the great work done by "Sindre Sorhus" and other collaborators of the [chalk](https://www.npmjs.com/package/chalk) project.
|
|
31
|
+
This project is not directly associated with chalk other than chalk being a core dependency of **Chronicle**.
|
|
32
|
+
|
|
33
|
+
**IMPORTANT**: Please note that although **Chronicle** can be configured to any color through chalk, your output is subject to your terminal's color limitations.
|
|
34
|
+
|
|
35
|
+
## Highlights
|
|
36
|
+
|
|
37
|
+
- Fully configurable
|
|
38
|
+
- Simple and Expressive API
|
|
39
|
+
- Highly performant
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
npm install node-chronicle
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
import Chronicle from 'node-chronicle';
|
|
51
|
+
|
|
52
|
+
const chronicle = new Chronicle();
|
|
53
|
+
|
|
54
|
+
chronicle.info('Info: sample application has started');
|
|
55
|
+
chronicle.warn('Warning: this is just a sample');
|
|
56
|
+
chronicle.error('Error: no application logic detected', true); // logs to logs/error.log file
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Easily define your own logging mechanism and color-coding preference:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
import Chronicle from 'node-chronicle';
|
|
63
|
+
|
|
64
|
+
const chronicle = new Chronicle({
|
|
65
|
+
systemLogs: {
|
|
66
|
+
blue: '#007cae', // indigo blue
|
|
67
|
+
yellow: '#ae8f00', // bright orange
|
|
68
|
+
red: 'red',
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
chronicle.blue('Info: using custom method blue, sample application has started');
|
|
73
|
+
chronicle.yellow('Warning: using custom method yellow, this is just a sample');
|
|
74
|
+
chronicle.red('Error: using custom method red, no application logic detected', false);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Customize logging options to best suit your project
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
import Chronicle from 'node-chronicle';
|
|
81
|
+
|
|
82
|
+
const chronicle = new Chronicle({
|
|
83
|
+
logToFileByDefault: true,
|
|
84
|
+
logTimestamp: true,
|
|
85
|
+
path: 'custom-logs', // <project root>/custom-logs/*.log
|
|
86
|
+
prefix: '--------------------------------------------------------------- \n',
|
|
87
|
+
suffix: '\n=============================================================== \n',
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
chronicle.info('Info: sample application has started');
|
|
91
|
+
```
|
|
92
|
+

|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
Add additional log types extending the default options of "info", "warn", "error" and "debug"
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
import Chronicle from '../source/index.js';
|
|
99
|
+
|
|
100
|
+
const chronicle = new Chronicle({ additionalLogs: { question: 'green' } });
|
|
101
|
+
|
|
102
|
+
// create additional log with direct chalk configuration
|
|
103
|
+
chronicle.defineType('query', chronicle.chalk().black.bgGreen);
|
|
104
|
+
|
|
105
|
+
chronicle.question('What will a fully custom chalk color function look like?');
|
|
106
|
+
await chronicle.query('This is what a custom chalk color setting looks like', true);
|
|
107
|
+
```
|
|
108
|
+

|
|
109
|
+
|
|
110
|
+
## API
|
|
111
|
+
|
|
112
|
+
### Defining Logs & Colors
|
|
113
|
+
|
|
114
|
+
By default, **Chronicle** is instantiated with the following options:
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
additionalLogs: {},
|
|
118
|
+
systemLogs: {
|
|
119
|
+
info: 'cyan',
|
|
120
|
+
warn: 'yellow',
|
|
121
|
+
error: 'red',
|
|
122
|
+
},
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
You can add to a new log/color setting by passing the `additionalLogs` option to the **Chronicle** constructor. Any setting that already exists in `systemLogs` will be replaced, otherwise they will be added.
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
const chronicle = new Chronicle({ additionalLogs: { info: 'green', custom: 'cyan' } });
|
|
129
|
+
|
|
130
|
+
// output configuration:
|
|
131
|
+
{
|
|
132
|
+
info: 'green',
|
|
133
|
+
warn: 'yellow',
|
|
134
|
+
error: 'red',
|
|
135
|
+
custom: 'cyan'
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Chronicle** will generate convenience methods for all keys provided, with the corresponding color settings. The example above would create the following convenience methods, for logging:
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
chronicle.info() // green output
|
|
143
|
+
chronicle.warn() // yellow output
|
|
144
|
+
chronicle.error() // red output
|
|
145
|
+
chronicle.custom() // cyan output
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
These methods can then be called in your application with [logging parameters](#logging-parameters).
|
|
149
|
+
|
|
150
|
+
Color settings are handled by determining whether your input is a color name or a hex value (prefixed with **#**). For example, passing `red` as a color setting will utilize `chalk.red`, while passing `#ff0000` would use `chalk.hex('#ff0000')` instead. A [list of available colors](https://github.com/chalk/chalk#colors) can be found in chalks' documentation.
|
|
151
|
+
|
|
152
|
+
Additionally, these methods return a promise when `logToFile` is true, allowing you use them with `await` in an async method, or append `then(), catch(), or finally()` for more advanced callback usage.
|
|
153
|
+
|
|
154
|
+
```js
|
|
155
|
+
async method() {
|
|
156
|
+
await chronicle.error('error message', true);
|
|
157
|
+
|
|
158
|
+
// do something after logs/error.log (default) is created
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### The Debug Method
|
|
163
|
+
|
|
164
|
+
**Chronicle** allows for the `chronicle.debug()` method to be overridden by a color setting. However, by default we do not define a color for debug and debug is handled differently. For console logging, all **debug** does is output the following:
|
|
165
|
+
|
|
166
|
+
```js
|
|
167
|
+
// For logging to console:
|
|
168
|
+
console.dir(content);
|
|
169
|
+
|
|
170
|
+
// For writing to file:
|
|
171
|
+
JSON.stringify(content, null, 2);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
We believe that when wanting to output complicated objects or debug **typescript** applications, there are better methods than utilizing this **Chronicle** package. But for anyone who's fully incorporated **Chronicle** into their project, this function offers some convenience.
|
|
175
|
+
|
|
176
|
+
### Logging Parameters
|
|
177
|
+
|
|
178
|
+
```js
|
|
179
|
+
chronicle.error('error message', true, false); // content, logToFile, overwrite
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
| Parameter | Type | Default | Description |
|
|
183
|
+
| :---: | :---: | :---: | :--- |
|
|
184
|
+
| `content` | **String** | | Content of log that will output on your console. |
|
|
185
|
+
| `logToFile` | **Boolean** | *false* | Option to log content to file. |
|
|
186
|
+
| `overwrite` | **Boolean** | *false <br> (true on debug())* | Option to overwrite log file, rather than append to it. This option is redundant if logToFile is false. |
|
|
187
|
+
|
|
188
|
+
**logToFile** will log to *<project-root>/logs* unless [configured](#configuration) differently during instantiation. <br>
|
|
189
|
+
### Configuration
|
|
190
|
+
|
|
191
|
+
When instantiating **Chronicle**, you can pass an object to customize your settings. Below is the default configuration:
|
|
192
|
+
|
|
193
|
+
```js
|
|
194
|
+
const chronicle = new Chronicle({
|
|
195
|
+
logToFileByDefault: false,
|
|
196
|
+
logTimestamp: false,
|
|
197
|
+
path: 'logs/',
|
|
198
|
+
prefix: '',
|
|
199
|
+
suffix: '',
|
|
200
|
+
additionalLogs: {},
|
|
201
|
+
systemLogs: {
|
|
202
|
+
info: 'cyan',
|
|
203
|
+
warn: 'yellow',
|
|
204
|
+
error: 'red',
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
| Option | Type | Default | Description |
|
|
210
|
+
| :---: | :---: | :---: | :--- |
|
|
211
|
+
| `logToFileByDefault` | **Boolean** | *false* | Option to change default setting for `logToFile` parameter of logging functions. |
|
|
212
|
+
| `logTimestamp` | **Boolean** | *false* | Option to include timestamp in console logging. Timestamps are automatically included in file logs. |
|
|
213
|
+
| `path` | **String** | *'logs/'* | Path in which to store log files. This setting is relative to your project's root directory. |
|
|
214
|
+
| `prefix` | **String** | *''* | Prefix string to prepend all log messages for all log types with the exception of *debug*. |
|
|
215
|
+
| `suffix` | **String** | *''* | Suffix string to tack on to all log messages for all log types with the exception of *debug*. |
|
|
216
|
+
| `additionalLogs` | **Object** | | Key value pair object containing log type to color setting for logs that will be merged with `systemLogs` |
|
|
217
|
+
| `systemLogs` | **Object** | | Key value pair object containing log type to color setting for main **Chronicle** logs available in application |
|
|
218
|
+
|
|
219
|
+
`additionalLogs` and `systemLogs` are explained with more detail in the [defining logs and colors](#defining-logs) section.
|
|
220
|
+
|
|
221
|
+
### Advanced Configuration
|
|
222
|
+
|
|
223
|
+
You may want to do more than just pick a basic color for your output. **chalk** offers a variety of different options, and can be configured via `defineType()`. **Chronicle** exposes the chalk instance via `chalk()` so that you don't have to import **chalk** directly into your project. Here is an example of how you can use this method to fully customize your log color setting:
|
|
224
|
+
|
|
225
|
+
```js
|
|
226
|
+
const chronicle = new Chronicle();
|
|
227
|
+
|
|
228
|
+
chronicle.defineType('critical', chronicle.chalk().bold.red);
|
|
229
|
+
chronicle.critical('This is a critical error');
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Additionally, any [configuration](#configuration) that can be set during instantiation, can also be applied exclusively to any given type by passing in a third **options** parameter.
|
|
233
|
+
|
|
234
|
+
```js
|
|
235
|
+
// params: type, setting, options
|
|
236
|
+
chronicle.definetype('notice', '#c0c0c0', {
|
|
237
|
+
prefix: '--------------------------------------------------------------- \n',
|
|
238
|
+
suffix: '\n=============================================================== \n'
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### defineType() params
|
|
243
|
+
| Parameter | Type | Description |
|
|
244
|
+
| :---: | :---: | :--- |
|
|
245
|
+
| `type` | **String** | Create or overwrites a logging function for the given type. |
|
|
246
|
+
| `setting` | **String or Function** | Color setting or chalk function |
|
|
247
|
+
| `options` | **Object** | Configure any setting only to the given type rather than globally. See [configuration](#configuration) for list of options |
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
```js
|
|
251
|
+
const chronicle = new Chronicle();
|
|
252
|
+
|
|
253
|
+
chronicle.defineType('info', chronicle.chalk().black.bgCyan);
|
|
254
|
+
chronicle.defineType('critical', chronicle.chalk().bold.red);
|
|
255
|
+
chronicle.defineType('dialog', 'magentaBright');
|
|
256
|
+
chronicle.definetype('notice', '#c0c0c0', {
|
|
257
|
+
prefix: '--------------------------------------------------------------- \n',
|
|
258
|
+
suffix: '\n=============================================================== \n'
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
chronicle.info('This pre-existing log now has a cyan background and black foreground');
|
|
262
|
+
chronicle.critical('This new log is bold and red');
|
|
263
|
+
chronicle.dialog('This new dialog is bright magenta');
|
|
264
|
+
chronicle.notice('This new log is the hex "#c0c0c0" share of gray');
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
`defineType()` can also be used as an alternative to populating the `additionalLogs` setting in the constructor, as if the setting doesn't already exist, it will then be created.
|
|
268
|
+
|
|
269
|
+
## Origin
|
|
270
|
+
|
|
271
|
+
As a team of developers who are constantly working on side projects, we often litter our codebase with TODOs to refactor convenience utils such as **chronicle** into classes of their own, or projects of their own. This usually turns into internal tech debt that never gets addressed. Furthermore, we also often find ourselves going the *copy -> paste -> modify* route of previously written useful logic, which saves us time in new projects, but not as much as it would if all we had to do was run an `npm install` instead.
|
|
272
|
+
|
|
273
|
+
With that in mind, we are proud to release **chronicle** as an open source package, in hopes others will find this just as useful as we do in their own projects.
|
|
274
|
+
|
|
275
|
+
## Maintainers
|
|
276
|
+
|
|
277
|
+
- [Stone Costa](https://github.com/mstonepc)
|
|
278
|
+
- [Daniel DeLima](https://github.com/danieldtech)
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stonyx/logs",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Simplified logging for node applications",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./color": "./src/color.js"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/abofs/stonyx-logs.git"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"log",
|
|
20
|
+
"logging",
|
|
21
|
+
"color-coding",
|
|
22
|
+
"chronicle",
|
|
23
|
+
"history",
|
|
24
|
+
"documentation",
|
|
25
|
+
"document",
|
|
26
|
+
"chalk",
|
|
27
|
+
"clean-output",
|
|
28
|
+
"terminal",
|
|
29
|
+
"debug"
|
|
30
|
+
],
|
|
31
|
+
"author": "Stone Costa",
|
|
32
|
+
"license": "ISC",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/abofs/stonyx-logs/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/abofs/stonyx-logs#readme",
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"chalk": "^5.3.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"eslint": "^8.27.0",
|
|
42
|
+
"eslint-plugin-node": "^11.1.0",
|
|
43
|
+
"qunit": "^2.19.3",
|
|
44
|
+
"sinon": "^17.0.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"test": "qunit 'test/unit/**/*-test.js'",
|
|
48
|
+
"lint": "eslint . --fix"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/color.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
|
|
3
|
+
export default class Color {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.types = [];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// retrieves configured color function for log type
|
|
9
|
+
getLogColor(type) {
|
|
10
|
+
return this.types[type];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getChalkInstance() {
|
|
14
|
+
return chalk;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
setLogColor(type, setting) {
|
|
18
|
+
const chalkColorFunction = this.settingToChalkColorFunction(setting);
|
|
19
|
+
this.types[type] = chalkColorFunction;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// retrieves chalk color function, and fully validates output
|
|
23
|
+
settingToChalkColorFunction(setting) {
|
|
24
|
+
const errorMessage = 'Invalid chalk color function.'
|
|
25
|
+
+ 'For help with color settings, see https://github.com/abofs/chronicle#defining-logs--colors';
|
|
26
|
+
|
|
27
|
+
switch (typeof setting) {
|
|
28
|
+
case 'string':
|
|
29
|
+
const chalkColorFunction = (setting[0] === '#') ? chalk.hex(setting) : chalk[setting];
|
|
30
|
+
if (!chalkColorFunction
|
|
31
|
+
|| typeof chalkColorFunction !== 'function'
|
|
32
|
+
|| typeof chalkColorFunction('') !== 'string') {
|
|
33
|
+
throw errorMessage;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return chalkColorFunction;
|
|
37
|
+
|
|
38
|
+
case 'function':
|
|
39
|
+
// validate that given function returns a string
|
|
40
|
+
if (typeof setting('') !== 'string') {
|
|
41
|
+
throw errorMessage;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return setting;
|
|
45
|
+
|
|
46
|
+
default:
|
|
47
|
+
throw errorMessage;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { mkdirSync, promises as fsp } from 'fs';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import projectPath from 'path';
|
|
4
|
+
import Color from './color.js';
|
|
5
|
+
|
|
6
|
+
const defaultOptions = {
|
|
7
|
+
logToFileByDefault: false, // default setting (overridable by logToFile param)
|
|
8
|
+
logTimestamp: false, // option to include timestamp in console logs
|
|
9
|
+
path: 'logs/', // default log directory (relative to main project root directory)
|
|
10
|
+
prefix: '',
|
|
11
|
+
suffix: '',
|
|
12
|
+
|
|
13
|
+
// log types with corresponding color settings
|
|
14
|
+
additionalLogs: {},
|
|
15
|
+
systemLogs: {
|
|
16
|
+
info: 'cyan',
|
|
17
|
+
warn: 'yellow',
|
|
18
|
+
error: 'red',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// used to sanitize defineType() options input
|
|
23
|
+
const optionKeys = Object.keys(defaultOptions);
|
|
24
|
+
|
|
25
|
+
export default class Chronicle {
|
|
26
|
+
constructor(options = defaultOptions) {
|
|
27
|
+
options = {
|
|
28
|
+
...defaultOptions,
|
|
29
|
+
...options,
|
|
30
|
+
};
|
|
31
|
+
this.options = options;
|
|
32
|
+
this.options.path = this.sanitizePath(this.options.path);
|
|
33
|
+
|
|
34
|
+
const { additionalLogs, systemLogs } = options;
|
|
35
|
+
const logs = {
|
|
36
|
+
...systemLogs,
|
|
37
|
+
...additionalLogs,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
this.color = new Color();
|
|
41
|
+
this.typeOptions = [];
|
|
42
|
+
|
|
43
|
+
// create direct convenience methods for logging
|
|
44
|
+
for (const type of Object.keys(logs)) {
|
|
45
|
+
this.defineType(type, logs[type]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// records setting and options for log type, and crates convenience method ie: chronicle.info()
|
|
50
|
+
defineType(type, setting, options = null) {
|
|
51
|
+
this.color.setLogColor(type, setting);
|
|
52
|
+
|
|
53
|
+
// create convenience method if it doesn't exist
|
|
54
|
+
if (!this[type]) this.createConvenienceMethod(type);
|
|
55
|
+
|
|
56
|
+
if (!options) return;
|
|
57
|
+
if (typeof options !== 'object') throw 'The options param must be an object.';
|
|
58
|
+
|
|
59
|
+
for (let option of Object.keys(options)) {
|
|
60
|
+
if (!optionKeys.includes(option)) {
|
|
61
|
+
throw `${option} is not a valid configuration object.`
|
|
62
|
+
+ '\n For a list of available options, see https://github.com/abofs/chronicle#configuration';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// sanitize path input
|
|
66
|
+
if (option === 'path') options[option] = this.sanitizePath(options[option]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this.typeOptions[type] = options;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// proxy through `logAction` method in order to set defaults based on argument presence
|
|
73
|
+
createConvenienceMethod(type) {
|
|
74
|
+
this[type] = (content, logToFile, overwrite = false) =>
|
|
75
|
+
this.logAction(type, content, logToFile, overwrite);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// validates params and sets configuration-based defaults for logging
|
|
79
|
+
logAction(type, content, logToFile, overwrite) {
|
|
80
|
+
// set logToFile default based on class options when not set
|
|
81
|
+
if (arguments[2] === undefined) logToFile = this.getOptionForType(type, 'logToFileByDefault');
|
|
82
|
+
|
|
83
|
+
// treat overwrite default as true for log type "debug"
|
|
84
|
+
if (type === 'debug' && arguments[3] === undefined) overwrite = true;
|
|
85
|
+
|
|
86
|
+
return this.log(content, type, logToFile, overwrite);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// retrieves option setting for given type, default to global
|
|
90
|
+
getOptionForType(type, option) {
|
|
91
|
+
const options = this.typeOptions[type];
|
|
92
|
+
if (!options || !options[option]) return this.options[option];
|
|
93
|
+
|
|
94
|
+
return options[option];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// exposes chalk for custom color options via defineType
|
|
98
|
+
chalk() {
|
|
99
|
+
return this.color.getChalkInstance();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// logs to console, and conditionally to file
|
|
103
|
+
async log(content, type, logToFile, overwrite) {
|
|
104
|
+
const logTimestamp = this.getOptionForType(type, 'logTimestamp');
|
|
105
|
+
const timestamp = `[${new Date().toLocaleString('en-US')}]`;
|
|
106
|
+
const chalkColorFunction = this.color.getLogColor(type);
|
|
107
|
+
let prefix = this.getOptionForType(type, 'prefix');
|
|
108
|
+
let suffix = this.getOptionForType(type, 'suffix');
|
|
109
|
+
if (logTimestamp) prefix += `${timestamp} `;
|
|
110
|
+
if (prefix) prefix = chalkColorFunction(prefix);
|
|
111
|
+
if (suffix) suffix = chalkColorFunction(suffix);
|
|
112
|
+
const coloredLog = chalkColorFunction(content);
|
|
113
|
+
|
|
114
|
+
console.log(`${prefix}${coloredLog}${suffix}`); // eslint-disable-line no-console
|
|
115
|
+
|
|
116
|
+
if (!logToFile) return;
|
|
117
|
+
|
|
118
|
+
return this.writeToFile(type, `${timestamp} ${content}\n`, overwrite);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// direct hardcoded debug method (log to file functionality is limited)
|
|
122
|
+
async debug(content, logToFile = false, overwrite = true) {
|
|
123
|
+
console.dir(content, { depth: 6 }); // eslint-disable-line no-console
|
|
124
|
+
|
|
125
|
+
if (!logToFile) return;
|
|
126
|
+
|
|
127
|
+
return this.writeToFile('debug', JSON.stringify(content, null, 2), overwrite);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async writeToFile(type, content, overwrite) {
|
|
131
|
+
const path = this.getOptionForType(type, 'path');
|
|
132
|
+
const targetLog = `${path}${type}.log`;
|
|
133
|
+
await this.validateFileAndDirectory(path, targetLog);
|
|
134
|
+
|
|
135
|
+
const fileAction = overwrite ? fsp.writeFile : fsp.appendFile;
|
|
136
|
+
|
|
137
|
+
return fileAction(targetLog, content);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// attempts to create file and/or directory if they don't already exist
|
|
141
|
+
async validateFileAndDirectory(path, targetLog) {
|
|
142
|
+
const errorMethod = this.error || console.error; // prefer native method unless removed by user
|
|
143
|
+
|
|
144
|
+
mkdirSync(path, { recursive: true });
|
|
145
|
+
|
|
146
|
+
await fsp.access(targetLog).catch(() => {
|
|
147
|
+
fsp.writeFile(targetLog, '').catch(() => {
|
|
148
|
+
errorMethod(`Failed to create log file: ${targetLog}.`
|
|
149
|
+
+ '\n Verify that the application runner has write permissions');
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// method to conditionally sanitize user configuration input
|
|
155
|
+
sanitizePath(path) {
|
|
156
|
+
const moduleDir = projectPath.dirname(fileURLToPath(import.meta.url));
|
|
157
|
+
const delim = moduleDir.includes('node_modules') ? 'node_modules' : 'src';
|
|
158
|
+
const splitDir = moduleDir.split(delim);
|
|
159
|
+
|
|
160
|
+
if (splitDir.length < 2) throw ('Failed to locate your project\'s root directory.');
|
|
161
|
+
|
|
162
|
+
// use project root directory behind path
|
|
163
|
+
path = projectPath.resolve(splitDir[0], path);
|
|
164
|
+
|
|
165
|
+
// force path property to contain a trailing "/"
|
|
166
|
+
if (path[path.length - 1] !== '/') {
|
|
167
|
+
path += '/';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return path;
|
|
171
|
+
}
|
|
172
|
+
}
|