@hardlydifficult/logger 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/README.md +117 -0
- package/dist/Logger.d.ts +15 -0
- package/dist/Logger.d.ts.map +1 -0
- package/dist/Logger.js +65 -0
- package/dist/Logger.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/ConsolePlugin.d.ts +6 -0
- package/dist/plugins/ConsolePlugin.d.ts.map +1 -0
- package/dist/plugins/ConsolePlugin.js +34 -0
- package/dist/plugins/ConsolePlugin.js.map +1 -0
- package/dist/plugins/DiscordPlugin.d.ts +9 -0
- package/dist/plugins/DiscordPlugin.d.ts.map +1 -0
- package/dist/plugins/DiscordPlugin.js +40 -0
- package/dist/plugins/DiscordPlugin.js.map +1 -0
- package/dist/plugins/FilePlugin.d.ts +7 -0
- package/dist/plugins/FilePlugin.d.ts.map +1 -0
- package/dist/plugins/FilePlugin.js +23 -0
- package/dist/plugins/FilePlugin.js.map +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# @hardlydifficult/logger
|
|
2
|
+
|
|
3
|
+
Plugin-based structured logger with Console, Discord, and File output plugins.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @hardlydifficult/logger
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Logger, ConsolePlugin, FilePlugin, DiscordPlugin } from "@hardlydifficult/logger";
|
|
15
|
+
|
|
16
|
+
const discord = new DiscordPlugin();
|
|
17
|
+
|
|
18
|
+
const logger = new Logger("info")
|
|
19
|
+
.use(new ConsolePlugin())
|
|
20
|
+
.use(new FilePlugin("/var/log/app.log"))
|
|
21
|
+
.use(discord);
|
|
22
|
+
|
|
23
|
+
// Wire up Discord sender once the bot is ready
|
|
24
|
+
discord.setSender((msg) => channel.send(msg));
|
|
25
|
+
|
|
26
|
+
logger.info("Server started", { port: 3000 });
|
|
27
|
+
logger.warn("High memory usage", { usage: "85%" });
|
|
28
|
+
logger.error("Request failed", { url: "/api/data", status: 500 });
|
|
29
|
+
|
|
30
|
+
// Out-of-band notification (goes to plugins that support notify)
|
|
31
|
+
logger.notify("Deployment complete");
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## API
|
|
35
|
+
|
|
36
|
+
### `Logger`
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
new Logger(minLevel?: LogLevel) // default: "info"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
| Method | Description |
|
|
43
|
+
|--------|-------------|
|
|
44
|
+
| `use(plugin)` | Register a plugin (returns `this` for chaining) |
|
|
45
|
+
| `debug(message, context?)` | Log at debug level |
|
|
46
|
+
| `info(message, context?)` | Log at info level |
|
|
47
|
+
| `warn(message, context?)` | Log at warn level |
|
|
48
|
+
| `error(message, context?)` | Log at error level |
|
|
49
|
+
| `notify(message)` | Send out-of-band notification to plugins that support it |
|
|
50
|
+
|
|
51
|
+
Log levels: `debug` < `info` < `warn` < `error`. Entries below `minLevel` are filtered out.
|
|
52
|
+
|
|
53
|
+
### Plugins
|
|
54
|
+
|
|
55
|
+
#### `ConsolePlugin`
|
|
56
|
+
|
|
57
|
+
Logs to `console.log`/`console.warn`/`console.error` with formatted timestamps.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
new ConsolePlugin()
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### `FilePlugin`
|
|
64
|
+
|
|
65
|
+
Appends JSON log entries to a file (one entry per line). Creates the directory if needed.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
new FilePlugin(filePath: string)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### `DiscordPlugin`
|
|
72
|
+
|
|
73
|
+
Sends warn/error logs and notifications to Discord. The sender is set lazily since the Discord connection may not be ready at logger creation time.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const discord = new DiscordPlugin();
|
|
77
|
+
discord.setSender((msg) => channel.send(msg));
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Custom Plugins
|
|
81
|
+
|
|
82
|
+
Implement the `LoggerPlugin` interface:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import type { LoggerPlugin, LogEntry } from "@hardlydifficult/logger";
|
|
86
|
+
|
|
87
|
+
class MyPlugin implements LoggerPlugin {
|
|
88
|
+
log(entry: LogEntry): void {
|
|
89
|
+
// Handle log entry
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Optional: handle notify() calls
|
|
93
|
+
notify?(message: string): void {
|
|
94
|
+
// Handle notification
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
logger.use(new MyPlugin());
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Types
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
105
|
+
|
|
106
|
+
interface LogEntry {
|
|
107
|
+
readonly level: LogLevel;
|
|
108
|
+
readonly message: string;
|
|
109
|
+
readonly timestamp: string;
|
|
110
|
+
readonly context?: Readonly<Record<string, unknown>>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
interface LoggerPlugin {
|
|
114
|
+
log(entry: LogEntry): void;
|
|
115
|
+
notify?(message: string): void;
|
|
116
|
+
}
|
|
117
|
+
```
|
package/dist/Logger.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { LoggerPlugin, LogLevel } from "./types.js";
|
|
2
|
+
export declare class Logger {
|
|
3
|
+
private readonly minLevel;
|
|
4
|
+
private readonly plugins;
|
|
5
|
+
constructor(minLevel?: LogLevel);
|
|
6
|
+
use(plugin: LoggerPlugin): this;
|
|
7
|
+
debug(message: string, context?: Readonly<Record<string, unknown>>): void;
|
|
8
|
+
info(message: string, context?: Readonly<Record<string, unknown>>): void;
|
|
9
|
+
warn(message: string, context?: Readonly<Record<string, unknown>>): void;
|
|
10
|
+
error(message: string, context?: Readonly<Record<string, unknown>>): void;
|
|
11
|
+
notify(message: string): void;
|
|
12
|
+
private shouldLog;
|
|
13
|
+
private log;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=Logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../src/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AASnE,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;gBAElC,QAAQ,GAAE,QAAiB;IAIvC,GAAG,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAK/B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI;IAIzE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI;IAIxE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI;IAIxE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI;IAIzE,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAY7B,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,GAAG;CAsBZ"}
|
package/dist/Logger.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = void 0;
|
|
4
|
+
const LOG_LEVELS = {
|
|
5
|
+
debug: 0,
|
|
6
|
+
info: 1,
|
|
7
|
+
warn: 2,
|
|
8
|
+
error: 3,
|
|
9
|
+
};
|
|
10
|
+
class Logger {
|
|
11
|
+
minLevel;
|
|
12
|
+
plugins = [];
|
|
13
|
+
constructor(minLevel = "info") {
|
|
14
|
+
this.minLevel = minLevel;
|
|
15
|
+
}
|
|
16
|
+
use(plugin) {
|
|
17
|
+
this.plugins.push(plugin);
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
debug(message, context) {
|
|
21
|
+
this.log("debug", message, context);
|
|
22
|
+
}
|
|
23
|
+
info(message, context) {
|
|
24
|
+
this.log("info", message, context);
|
|
25
|
+
}
|
|
26
|
+
warn(message, context) {
|
|
27
|
+
this.log("warn", message, context);
|
|
28
|
+
}
|
|
29
|
+
error(message, context) {
|
|
30
|
+
this.log("error", message, context);
|
|
31
|
+
}
|
|
32
|
+
notify(message) {
|
|
33
|
+
for (const plugin of this.plugins) {
|
|
34
|
+
if (plugin.notify) {
|
|
35
|
+
try {
|
|
36
|
+
plugin.notify(message);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
/* swallow */
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
shouldLog(level) {
|
|
45
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[this.minLevel];
|
|
46
|
+
}
|
|
47
|
+
log(level, message, context) {
|
|
48
|
+
if (!this.shouldLog(level)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const entry = context !== undefined
|
|
52
|
+
? { level, message, timestamp: new Date().toISOString(), context }
|
|
53
|
+
: { level, message, timestamp: new Date().toISOString() };
|
|
54
|
+
for (const plugin of this.plugins) {
|
|
55
|
+
try {
|
|
56
|
+
plugin.log(entry);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
/* swallow */
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.Logger = Logger;
|
|
65
|
+
//# sourceMappingURL=Logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Logger.js","sourceRoot":"","sources":["../src/Logger.ts"],"names":[],"mappings":";;;AAEA,MAAM,UAAU,GAAuC;IACrD,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,MAAa,MAAM;IACA,QAAQ,CAAW;IACnB,OAAO,GAAmB,EAAE,CAAC;IAE9C,YAAY,WAAqB,MAAM;QACrC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,GAAG,CAAC,MAAoB;QACtB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,OAA2C;QAChE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,OAA2C;QAC/D,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,OAA2C;QAC/D,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,OAA2C;QAChE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,CAAC,OAAe;QACpB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,IAAI,CAAC;oBACH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACzB,CAAC;gBAAC,MAAM,CAAC;oBACP,aAAa;gBACf,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,KAAe;QAC/B,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxD,CAAC;IAEO,GAAG,CACT,KAAe,EACf,OAAe,EACf,OAA2C;QAE3C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GACT,OAAO,KAAK,SAAS;YACnB,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE;YAClE,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QAE9D,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;YAAC,MAAM,CAAC;gBACP,aAAa;YACf,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAnED,wBAmEC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { Logger } from "./Logger.js";
|
|
2
|
+
export { ConsolePlugin, formatEntry } from "./plugins/ConsolePlugin.js";
|
|
3
|
+
export { DiscordPlugin, type DiscordSender } from "./plugins/DiscordPlugin.js";
|
|
4
|
+
export { FilePlugin } from "./plugins/FilePlugin.js";
|
|
5
|
+
export type { LogLevel, LogEntry, LoggerPlugin } from "./types.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FilePlugin = exports.DiscordPlugin = exports.formatEntry = exports.ConsolePlugin = exports.Logger = void 0;
|
|
4
|
+
var Logger_js_1 = require("./Logger.js");
|
|
5
|
+
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return Logger_js_1.Logger; } });
|
|
6
|
+
var ConsolePlugin_js_1 = require("./plugins/ConsolePlugin.js");
|
|
7
|
+
Object.defineProperty(exports, "ConsolePlugin", { enumerable: true, get: function () { return ConsolePlugin_js_1.ConsolePlugin; } });
|
|
8
|
+
Object.defineProperty(exports, "formatEntry", { enumerable: true, get: function () { return ConsolePlugin_js_1.formatEntry; } });
|
|
9
|
+
var DiscordPlugin_js_1 = require("./plugins/DiscordPlugin.js");
|
|
10
|
+
Object.defineProperty(exports, "DiscordPlugin", { enumerable: true, get: function () { return DiscordPlugin_js_1.DiscordPlugin; } });
|
|
11
|
+
var FilePlugin_js_1 = require("./plugins/FilePlugin.js");
|
|
12
|
+
Object.defineProperty(exports, "FilePlugin", { enumerable: true, get: function () { return FilePlugin_js_1.FilePlugin; } });
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAAqC;AAA5B,mGAAA,MAAM,OAAA;AACf,+DAAwE;AAA/D,iHAAA,aAAa,OAAA;AAAE,+GAAA,WAAW,OAAA;AACnC,+DAA+E;AAAtE,iHAAA,aAAa,OAAA;AACtB,yDAAqD;AAA5C,2GAAA,UAAU,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConsolePlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/ConsolePlugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAMnD;AAED,qBAAa,aAAc,YAAW,YAAY;IAChD,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAmB3B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConsolePlugin = void 0;
|
|
4
|
+
exports.formatEntry = formatEntry;
|
|
5
|
+
function formatEntry(entry) {
|
|
6
|
+
const base = `[${entry.timestamp}] ${entry.level.toUpperCase()}: ${entry.message}`;
|
|
7
|
+
if (entry.context && Object.keys(entry.context).length > 0) {
|
|
8
|
+
return `${base} ${JSON.stringify(entry.context)}`;
|
|
9
|
+
}
|
|
10
|
+
return base;
|
|
11
|
+
}
|
|
12
|
+
class ConsolePlugin {
|
|
13
|
+
log(entry) {
|
|
14
|
+
const formatted = formatEntry(entry);
|
|
15
|
+
switch (entry.level) {
|
|
16
|
+
case "debug":
|
|
17
|
+
case "info":
|
|
18
|
+
// eslint-disable-next-line no-console
|
|
19
|
+
console.log(formatted);
|
|
20
|
+
break;
|
|
21
|
+
case "warn":
|
|
22
|
+
console.warn(formatted);
|
|
23
|
+
break;
|
|
24
|
+
case "error":
|
|
25
|
+
console.error(formatted);
|
|
26
|
+
break;
|
|
27
|
+
default:
|
|
28
|
+
console.warn(formatted);
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.ConsolePlugin = ConsolePlugin;
|
|
34
|
+
//# sourceMappingURL=ConsolePlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConsolePlugin.js","sourceRoot":"","sources":["../../src/plugins/ConsolePlugin.ts"],"names":[],"mappings":";;;AAEA,kCAMC;AAND,SAAgB,WAAW,CAAC,KAAe;IACzC,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;IACnF,IAAI,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3D,OAAO,GAAG,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAa,aAAa;IACxB,GAAG,CAAC,KAAe;QACjB,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QACrC,QAAQ,KAAK,CAAC,KAAK,EAAE,CAAC;YACpB,KAAK,OAAO,CAAC;YACb,KAAK,MAAM;gBACT,sCAAsC;gBACtC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBACvB,MAAM;YACR,KAAK,MAAM;gBACT,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACxB,MAAM;YACR,KAAK,OAAO;gBACV,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBACzB,MAAM;YACR;gBACE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACxB,MAAM;QACV,CAAC;IACH,CAAC;CACF;AApBD,sCAoBC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LogEntry, LoggerPlugin } from "../types.js";
|
|
2
|
+
export type DiscordSender = (message: string) => void;
|
|
3
|
+
export declare class DiscordPlugin implements LoggerPlugin {
|
|
4
|
+
private sender;
|
|
5
|
+
setSender(sender: DiscordSender): void;
|
|
6
|
+
log(entry: LogEntry): void;
|
|
7
|
+
notify(message: string): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=DiscordPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscordPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/DiscordPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAEtD,qBAAa,aAAc,YAAW,YAAY;IAChD,OAAO,CAAC,MAAM,CAA8B;IAE5C,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAItC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAqB1B,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAU9B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DiscordPlugin = void 0;
|
|
4
|
+
class DiscordPlugin {
|
|
5
|
+
sender = null;
|
|
6
|
+
setSender(sender) {
|
|
7
|
+
this.sender = sender;
|
|
8
|
+
}
|
|
9
|
+
log(entry) {
|
|
10
|
+
if (!this.sender) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (entry.level !== "warn" && entry.level !== "error") {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const prefix = entry.level === "error" ? "\u{1f6a8}" : "\u{26a0}\u{fe0f}";
|
|
17
|
+
const discordMessage = entry.context && Object.keys(entry.context).length > 0
|
|
18
|
+
? `${prefix} **${entry.level.toUpperCase()}**: ${entry.message}\n\`\`\`json\n${JSON.stringify(entry.context, null, 2)}\n\`\`\``
|
|
19
|
+
: `${prefix} **${entry.level.toUpperCase()}**: ${entry.message}`;
|
|
20
|
+
try {
|
|
21
|
+
this.sender(discordMessage);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
/* swallow */
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
notify(message) {
|
|
28
|
+
if (!this.sender) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
this.sender(message);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
/* swallow */
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.DiscordPlugin = DiscordPlugin;
|
|
40
|
+
//# sourceMappingURL=DiscordPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscordPlugin.js","sourceRoot":"","sources":["../../src/plugins/DiscordPlugin.ts"],"names":[],"mappings":";;;AAIA,MAAa,aAAa;IAChB,MAAM,GAAyB,IAAI,CAAC;IAE5C,SAAS,CAAC,MAAqB;QAC7B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,GAAG,CAAC,KAAe;QACjB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;YACtD,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC;QAC1E,MAAM,cAAc,GAClB,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC;YACpD,CAAC,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,KAAK,CAAC,OAAO,iBAAiB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,UAAU;YAC/H,CAAC,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC;QAErE,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,aAAa;QACf,CAAC;IACH,CAAC;IAED,MAAM,CAAC,OAAe;QACpB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,aAAa;QACf,CAAC;IACH,CAAC;CACF;AAtCD,sCAsCC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilePlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/FilePlugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE1D,qBAAa,UAAW,YAAW,YAAY;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,QAAQ,EAAE,MAAM;IAK5B,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAQ3B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FilePlugin = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
class FilePlugin {
|
|
7
|
+
filePath;
|
|
8
|
+
constructor(filePath) {
|
|
9
|
+
this.filePath = filePath;
|
|
10
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(filePath), { recursive: true });
|
|
11
|
+
}
|
|
12
|
+
log(entry) {
|
|
13
|
+
const line = `${JSON.stringify(entry)}\n`;
|
|
14
|
+
try {
|
|
15
|
+
(0, node_fs_1.appendFileSync)(this.filePath, line);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
/* swallow */
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.FilePlugin = FilePlugin;
|
|
23
|
+
//# sourceMappingURL=FilePlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilePlugin.js","sourceRoot":"","sources":["../../src/plugins/FilePlugin.ts"],"names":[],"mappings":";;;AAAA,qCAAoD;AACpD,yCAAoC;AAIpC,MAAa,UAAU;IACJ,QAAQ,CAAS;IAElC,YAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAA,mBAAS,EAAC,IAAA,mBAAO,EAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,GAAG,CAAC,KAAe;QACjB,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;QAC1C,IAAI,CAAC;YACH,IAAA,wBAAc,EAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,aAAa;QACf,CAAC;IACH,CAAC;CACF;AAhBD,gCAgBC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
2
|
+
export interface LogEntry {
|
|
3
|
+
readonly level: LogLevel;
|
|
4
|
+
readonly message: string;
|
|
5
|
+
readonly timestamp: string;
|
|
6
|
+
readonly context?: Readonly<Record<string, unknown>>;
|
|
7
|
+
}
|
|
8
|
+
export interface LoggerPlugin {
|
|
9
|
+
/** Called for each log entry that passes the level filter. */
|
|
10
|
+
log(entry: LogEntry): void;
|
|
11
|
+
/** Called for notify() — out-of-band notifications. Optional. */
|
|
12
|
+
notify?(message: string): void;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3B,iEAAiE;IACjE,MAAM,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hardlydifficult/logger",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
|
+
"types": "./dist/index.d.ts",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"test": "vitest run",
|
|
12
|
+
"test:watch": "vitest",
|
|
13
|
+
"test:coverage": "vitest run --coverage",
|
|
14
|
+
"lint": "tsc --noEmit",
|
|
15
|
+
"clean": "rm -rf dist"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "20.19.31",
|
|
19
|
+
"typescript": "5.8.3",
|
|
20
|
+
"vitest": "1.6.1"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|