@deployanyway/doggo-log 0.1.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,7 +1,18 @@
1
- # Changelog
2
-
3
- ## 0.1.0 — Unreleased
4
-
5
- - Six logging methods, level filtering, quiet mode, and custom prefixes.
6
- - Optional emojis, ANSI colors, timestamps, and JSON output.
7
- - CLI, tests, documentation, and Node 22/24 CI.
1
+ # Changelog
2
+
3
+ ## 0.2.0 — 2026-10-08
4
+
5
+ - Scoped logs, optional barks: Use `logger.child("database")` to create an independent logger with a nested prefix. Enable `{ bark: true }` or CLI `--bark` for dog commentary. JSON preserves the original message and adds a separate `commentary` field. Filtering still suppresses output.
6
+ - Add npm and CI badges to the published README.
7
+
8
+ ## 0.1.1 — 2026-10-08
9
+
10
+ - Correct npm installation and npx documentation after the initial publication.
11
+ - Add a searchable, humorous package description and relevant npm keywords.
12
+ - No API, CLI behavior, or dependency changes.
13
+
14
+ ## 0.1.0 — 2026-10-08
15
+
16
+ - Six logging methods, level filtering, quiet mode, and custom prefixes.
17
+ - Optional emojis, ANSI colors, timestamps, and JSON output.
18
+ - CLI, tests, documentation, and Node 22/24 CI.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Deploy Anyway
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Deploy Anyway
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,141 +1,161 @@
1
- # doggo-log
2
-
3
- A tiny dog-themed logger with useful output and good manners.
4
-
5
- ```text
6
- 🐶 INFO Server started
7
- 🐾 SUCCESS Tests passed
8
- 🦴 WARN API is getting slow
9
- 🚨 ERROR Database connection failed
10
- ```
11
-
12
- ## Installation
13
-
14
- Version 0.1.0 has not been published to npm. Try from source with Node 22 or 24:
15
-
16
- ```sh
17
- git clone https://github.com/DeployAnyway/doggo-log.git
18
- cd doggo-log
19
- git checkout feature/initial-mvp
20
- npm ci
21
- node examples/basic.js
22
- ```
23
-
24
- After an approved release: `npm install @deployanyway/doggo-log`.
25
-
26
- ## Quick start
27
-
28
- ```js
29
- import { doglog, createDogLogger } from "@deployanyway/doggo-log";
30
-
31
- doglog.info("Server started");
32
- doglog.success("Tests passed");
33
- doglog.warn("API is getting slow");
34
- doglog.error("Database connection failed");
35
-
36
- const logger = createDogLogger({
37
- timestamp: true,
38
- level: "debug",
39
- prefix: "app",
40
- });
41
- logger.debug("Listening on port %d", 3000);
42
- ```
43
-
44
- ## CLI example
45
-
46
- ```sh
47
- node bin/cli.js success "Tests passed" --no-emoji
48
- node bin/cli.js info "Server started" --json --timestamp
49
- ```
50
-
51
- After publication: `npx @deployanyway/doggo-log info "Server started"`.
52
-
53
- ## API
54
-
55
- `doglog` is the default logger. `createDogLogger(options = {})` makes an independent
56
- logger. Both expose `log`, `info`, `success`, `warn`, `error`, and `debug`.
57
- Methods accept the same message arguments as Node's `util.format`, including
58
- format placeholders, objects, and Error instances. Zero arguments log the label
59
- alone. Each method returns its emitted string, or undefined if filtered/quiet.
60
-
61
- Default output sends warn/error to stderr and other methods to stdout. Logging
62
- an error does not set an exit code. The library never calls process.exit.
63
- Errors from a custom output function propagate to the caller.
64
-
65
- ## Options
66
-
67
- | Option | Default | Behavior |
68
- | ----------- | -------------- | ------------------------------------------------------ |
69
- | `emoji` | true | Dog-themed level symbols |
70
- | `color` | false | ANSI color for text lines; ignored for JSON |
71
- | `timestamp` | false | UTC ISO timestamp |
72
- | `json` | false | One JSON object per call; emoji/color omitted |
73
- | `quiet` | false | Suppress all output |
74
- | `prefix` | empty string | Text prefix or JSON prefix field |
75
- | `level` | info | Minimum level |
76
- | `write` | console output | Function `(line, level)` for each emitted line |
77
- | `clock` | current Date | Function returning a valid Date when timestamp enabled |
78
-
79
- Levels: debug (10), log/info/success (20), warn (30), error (40). Thresholds
80
- include all levels with equal or higher ranks. At info, debug is suppressed.
81
- At warn, only warn and error appear. JSON always includes `level` and `message`,
82
- with `prefix` and `timestamp` included when enabled/nonempty. Object arguments
83
- are formatted into the message string; they are not separate JSON fields.
84
-
85
- Invalid options throw TypeError; unknown levels throw RangeError. Names are case
86
- sensitive. Unknown option keys are ignored. Quiet/filtered calls skip message
87
- formatting, clock calls, and output. No transports, rotation, telemetry, remote
88
- service, or production dependencies are required.
89
-
90
- ## CLI reference
91
-
92
- `doggo-log <method> <message> [options]`
93
-
94
- | Flag | Behavior |
95
- | ----------------- | --------------------------------- |
96
- | `--json` | JSON output |
97
- | `--timestamp` | ISO timestamp |
98
- | `--no-emoji` | Plain labels |
99
- | `--color` | ANSI color |
100
- | `--prefix text` | Prefix |
101
- | `--level name` | Minimum level (CLI default debug) |
102
- | `--quiet` | Suppress output |
103
- | `--help`, `-h` | Usage |
104
- | `--version`, `-v` | Version |
105
-
106
- Quote messages containing shell punctuation. Use `--` before positional arguments
107
- containing dash-prefixed text. CLI messages are strings, without placeholder
108
- interpolation. Exit 0 means success (including filtered calls and error logging);
109
- exit 2 means invalid arguments. No stdin support in this MVP.
110
-
111
- ## Development and examples
112
-
113
- ```sh
114
- npm ci
115
- node examples/basic.js
116
- npm test
117
- npm run lint
118
- npm run format:check
119
- npm pack --dry-run
120
- ```
121
-
122
- ES modules and Node's test runner. CI runs Node 22/24. Development tooling requires
123
- Node 22.13+ or 24. Styles and behavior are separate for easy contributions.
124
-
125
- ## Contributing
126
-
127
- See [CONTRIBUTING.md](CONTRIBUTING.md).
128
-
129
- ## License
130
-
131
- [MIT](LICENSE).
132
-
133
- ## More from DeployAnyway
134
-
135
- **Tools for developers who probably know better.**
136
-
137
- - [error-translator](https://github.com/DeployAnyway/error-translator)
138
- - [excuse-js](https://github.com/DeployAnyway/excuse-js)
139
- - [doggo-log](https://github.com/DeployAnyway/doggo-log)
140
- - [ship-it-meter](https://github.com/DeployAnyway/ship-it-meter)
141
- - [bro-say](https://github.com/DeployAnyway/bro-say)
1
+ # doggo-log
2
+
3
+ [![npm version](https://img.shields.io/npm/v/%40deployanyway%2Fdoggo-log)](https://www.npmjs.com/package/@deployanyway/doggo-log)
4
+ [![CI](https://github.com/DeployAnyway/doggo-log/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/DeployAnyway/doggo-log/actions/workflows/ci.yml)
5
+
6
+ A tiny Node.js console logger with JSON output, log levels, and dog emojis. Good logs. Very good logs.
7
+
8
+ ```text
9
+ 🐶 INFO Server started
10
+ 🐾 SUCCESS Tests passed
11
+ 🦴 WARN API is getting slow
12
+ 🚨 ERROR Database connection failed
13
+ ```
14
+
15
+ ## Installation
16
+
17
+ Available on npm. Requires Node 22 or later.
18
+ You can also run from source with Node 22 or 24:
19
+
20
+ ```sh
21
+ git clone https://github.com/DeployAnyway/doggo-log.git
22
+ cd doggo-log
23
+ git checkout main
24
+ npm ci
25
+ node examples/basic.js
26
+ ```
27
+
28
+ Install from npm: `npm install @deployanyway/doggo-log`.
29
+
30
+ ## Quick start
31
+
32
+ ```js
33
+ import { doglog, createDogLogger } from "@deployanyway/doggo-log";
34
+
35
+ doglog.info("Server started");
36
+ doglog.success("Tests passed");
37
+ doglog.warn("API is getting slow");
38
+ doglog.error("Database connection failed");
39
+
40
+ const logger = createDogLogger({
41
+ timestamp: true,
42
+ level: "debug",
43
+ prefix: "app",
44
+ });
45
+ logger.debug("Listening on port %d", 3000);
46
+ ```
47
+
48
+ ## CLI example
49
+
50
+ ```sh
51
+ node bin/cli.js success "Tests passed" --no-emoji
52
+ node bin/cli.js info "Server started" --json --timestamp
53
+ ```
54
+
55
+ Run with npx: `npx @deployanyway/doggo-log info "Server started"`.
56
+
57
+ ## API
58
+
59
+ `doglog` is the default logger. `createDogLogger(options = {})` makes an independent
60
+ logger. Both expose `log`, `info`, `success`, `warn`, `error`, and `debug`.
61
+ Methods accept the same message arguments as Node's `util.format`, including
62
+ format placeholders, objects, and Error instances. Zero arguments log the label
63
+ alone. Each method returns its emitted string, or undefined if filtered/quiet.
64
+
65
+ Default output sends warn/error to stderr and other methods to stdout. Logging
66
+ an error does not set an exit code. The library never calls process.exit.
67
+ Errors from a custom output function propagate to the caller.
68
+
69
+ ## Options
70
+
71
+ | Option | Default | Behavior |
72
+ | ----------- | -------------- | ------------------------------------------------------ |
73
+ | `emoji` | true | Dog-themed level symbols |
74
+ | `color` | false | ANSI color for text lines; ignored for JSON |
75
+ | `timestamp` | false | UTC ISO timestamp |
76
+ | `json` | false | One JSON object per call; emoji/color omitted |
77
+ | `quiet` | false | Suppress all output |
78
+ | `prefix` | empty string | Text prefix or JSON prefix field |
79
+ | `level` | info | Minimum level |
80
+ | `write` | console output | Function `(line, level)` for each emitted line |
81
+ | `clock` | current Date | Function returning a valid Date when timestamp enabled |
82
+
83
+ Levels: debug (10), log/info/success (20), warn (30), error (40). Thresholds
84
+ include all levels with equal or higher ranks. At info, debug is suppressed.
85
+ At warn, only warn and error appear. JSON always includes `level` and `message`,
86
+ with `prefix` and `timestamp` included when enabled/nonempty. Object arguments
87
+ are formatted into the message string; they are not separate JSON fields.
88
+
89
+ Invalid options throw TypeError; unknown levels throw RangeError. Names are case
90
+ sensitive. Unknown option keys are ignored. Quiet/filtered calls skip message
91
+ formatting, clock calls, and output. No transports, rotation, telemetry, remote
92
+ service, or production dependencies are required.
93
+
94
+ ## CLI reference
95
+
96
+ `doggo-log <method> <message> [options]`
97
+
98
+ | Flag | Behavior |
99
+ | ----------------- | --------------------------------- |
100
+ | `--json` | JSON output |
101
+ | `--timestamp` | ISO timestamp |
102
+ | `--no-emoji` | Plain labels |
103
+ | `--color` | ANSI color |
104
+ | `--prefix text` | Prefix |
105
+ | `--level name` | Minimum level (CLI default debug) |
106
+ | `--quiet` | Suppress output |
107
+ | `--help`, `-h` | Usage |
108
+ | `--version`, `-v` | Version |
109
+
110
+ Quote messages containing shell punctuation. Use `--` before positional arguments
111
+ containing dash-prefixed text. CLI messages are strings, without placeholder
112
+ interpolation. Exit 0 means success (including filtered calls and error logging);
113
+ exit 2 means invalid arguments. No stdin support in this MVP.
114
+
115
+ ## Development and examples
116
+
117
+ ```sh
118
+ npm ci
119
+ node examples/basic.js
120
+ npm test
121
+ npm run lint
122
+ npm run format:check
123
+ npm pack --dry-run
124
+ ```
125
+
126
+ ES modules and Node's test runner. CI runs Node 22/24. Development tooling requires
127
+ Node 22.13+ or 24. Styles and behavior are separate for easy contributions.
128
+
129
+ ## Contributing
130
+
131
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
132
+
133
+ ## License
134
+
135
+ [MIT](LICENSE).
136
+
137
+ ## More from DeployAnyway
138
+
139
+ **Tools for developers who probably know better.**
140
+
141
+ - [error-translator](https://github.com/DeployAnyway/error-translator)
142
+ - [excuse-js](https://github.com/DeployAnyway/excuse-js)
143
+ - [doggo-log](https://github.com/DeployAnyway/doggo-log)
144
+ - [ship-it-meter](https://github.com/DeployAnyway/ship-it-meter)
145
+ - [bro-say](https://github.com/DeployAnyway/bro-say)
146
+
147
+ ## Scoped logs, optional barks
148
+
149
+ Use `logger.child("database")` to create an independent logger with a nested prefix. Enable `{ bark: true }` or CLI `--bark` for dog commentary. JSON preserves the original message and adds a separate `commentary` field. Filtering still suppresses output.
150
+
151
+ ```sh
152
+ npx @deployanyway/doggo-log success "Migration complete" --bark --prefix database
153
+ ```
154
+
155
+ API (import the named functions from this package):
156
+
157
+ ```js
158
+ createDogLogger({ bark: true, prefix: "api" })
159
+ .child("database")
160
+ .success("Migration complete");
161
+ ```
package/bin/cli.js CHANGED
@@ -1,51 +1,53 @@
1
- #!/usr/bin/env node
2
- import { parseArgs } from "node:util";
3
- import { readFileSync } from "node:fs";
4
- import { URL } from "node:url";
5
- import { createDogLogger } from "../src/index.js";
6
- import { levels } from "../src/levels.js";
7
-
8
- try {
9
- const { values, positionals } = parseArgs({
10
- allowPositionals: true,
11
- options: {
12
- help: { type: "boolean", short: "h" },
13
- version: { type: "boolean", short: "v" },
14
- json: { type: "boolean" },
15
- timestamp: { type: "boolean" },
16
- quiet: { type: "boolean" },
17
- color: { type: "boolean" },
18
- "no-emoji": { type: "boolean" },
19
- prefix: { type: "string" },
20
- level: { type: "string", default: "debug" },
21
- },
22
- });
23
- if (values.help) {
24
- console.log(
25
- "Usage: doggo-log <method> <message> [options]\n\nMethods: log, info, success, warn, error, debug\nOptions:\n --json Emit JSON\n --timestamp Include an ISO timestamp\n --no-emoji Disable emojis\n --color Enable ANSI colors\n --prefix text Add a prefix\n --level name Minimum level (CLI default: debug)\n --quiet Suppress output\n -h, --help Show help\n -v, --version Show version\n\nExit codes: 0 success; 2 invalid arguments. Logging an error exits 0.",
26
- );
27
- } else if (values.version) {
28
- console.log(
29
- JSON.parse(
30
- readFileSync(new URL("../package.json", import.meta.url), "utf8"),
31
- ).version,
32
- );
33
- } else {
34
- const [method, ...message] = positionals;
35
- if (!Object.hasOwn(levels, method ?? "") || !message.join(" ").trim())
36
- throw new TypeError("Provide a valid method and nonempty message.");
37
- const logger = createDogLogger({
38
- emoji: !values["no-emoji"],
39
- color: values.color ?? false,
40
- timestamp: values.timestamp ?? false,
41
- json: values.json ?? false,
42
- quiet: values.quiet ?? false,
43
- prefix: values.prefix ?? "",
44
- level: values.level,
45
- });
46
- logger[method](message.join(" "));
47
- }
48
- } catch (error) {
49
- console.error(`doggo-log: ${error.message}\nRun with --help for usage.`);
50
- process.exitCode = 2;
51
- }
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { readFileSync } from "node:fs";
4
+ import { URL } from "node:url";
5
+ import { createDogLogger } from "../src/index.js";
6
+ import { levels } from "../src/levels.js";
7
+
8
+ try {
9
+ const { values, positionals } = parseArgs({
10
+ allowPositionals: true,
11
+ options: {
12
+ help: { type: "boolean", short: "h" },
13
+ version: { type: "boolean", short: "v" },
14
+ json: { type: "boolean" },
15
+ bark: { type: "boolean" },
16
+ timestamp: { type: "boolean" },
17
+ quiet: { type: "boolean" },
18
+ color: { type: "boolean" },
19
+ "no-emoji": { type: "boolean" },
20
+ prefix: { type: "string" },
21
+ level: { type: "string", default: "debug" },
22
+ },
23
+ });
24
+ if (values.help) {
25
+ console.log(
26
+ "Usage: doggo-log <method> <message> [options]\n\nMethods: log, info, success, warn, error, debug\nOptions:\n --bark Add useful dog commentary\n --json Emit JSON\n --timestamp Include an ISO timestamp\n --no-emoji Disable emojis\n --color Enable ANSI colors\n --prefix text Add a prefix\n --level name Minimum level (CLI default: debug)\n --quiet Suppress output\n -h, --help Show help\n -v, --version Show version\n\nExit codes: 0 success; 2 invalid arguments. Logging an error exits 0.",
27
+ );
28
+ } else if (values.version) {
29
+ console.log(
30
+ JSON.parse(
31
+ readFileSync(new URL("../package.json", import.meta.url), "utf8"),
32
+ ).version,
33
+ );
34
+ } else {
35
+ const [method, ...message] = positionals;
36
+ if (!Object.hasOwn(levels, method ?? "") || !message.join(" ").trim())
37
+ throw new TypeError("Provide a valid method and nonempty message.");
38
+ const logger = createDogLogger({
39
+ emoji: !values["no-emoji"],
40
+ bark: values.bark ?? false,
41
+ color: values.color ?? false,
42
+ timestamp: values.timestamp ?? false,
43
+ json: values.json ?? false,
44
+ quiet: values.quiet ?? false,
45
+ prefix: values.prefix ?? "",
46
+ level: values.level,
47
+ });
48
+ logger[method](message.join(" "));
49
+ }
50
+ } catch (error) {
51
+ console.error(`doggo-log: ${error.message}\nRun with --help for usage.`);
52
+ process.exitCode = 2;
53
+ }
package/package.json CHANGED
@@ -1,41 +1,53 @@
1
- {
2
- "name": "@deployanyway/doggo-log",
3
- "version": "0.1.0",
4
- "description": "A tiny dog-themed logger with useful output and good manners.",
5
- "type": "module",
6
- "exports": "./src/index.js",
7
- "bin": {
8
- "doggo-log": "./bin/cli.js"
9
- },
10
- "files": [
11
- "src",
12
- "bin",
13
- "README.md",
14
- "LICENSE",
15
- "CHANGELOG.md"
16
- ],
17
- "engines": {
18
- "node": ">=22"
19
- },
20
- "scripts": {
21
- "test": "node --test",
22
- "lint": "eslint .",
23
- "format": "prettier --write .",
24
- "format:check": "prettier --check ."
25
- },
26
- "repository": {
27
- "type": "git",
28
- "url": "git+https://github.com/DeployAnyway/doggo-log.git"
29
- },
30
- "bugs": {
31
- "url": "https://github.com/DeployAnyway/doggo-log/issues"
32
- },
33
- "license": "MIT",
34
- "publishConfig": {
35
- "access": "public"
36
- },
37
- "devDependencies": {
38
- "eslint": "^10.12.0",
39
- "prettier": "^3.6.2"
40
- }
41
- }
1
+ {
2
+ "name": "@deployanyway/doggo-log",
3
+ "version": "0.2.0",
4
+ "description": "A tiny Node.js console logger with JSON output, log levels, and dog emojis. Good logs. Very good logs.",
5
+ "type": "module",
6
+ "exports": "./src/index.js",
7
+ "bin": {
8
+ "doggo-log": "./bin/cli.js"
9
+ },
10
+ "files": [
11
+ "src",
12
+ "bin",
13
+ "README.md",
14
+ "LICENSE",
15
+ "CHANGELOG.md"
16
+ ],
17
+ "engines": {
18
+ "node": ">=22"
19
+ },
20
+ "scripts": {
21
+ "test": "node --test",
22
+ "lint": "eslint .",
23
+ "format": "prettier --write .",
24
+ "format:check": "prettier --check ."
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/DeployAnyway/doggo-log.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/DeployAnyway/doggo-log/issues"
32
+ },
33
+ "license": "MIT",
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "devDependencies": {
38
+ "eslint": "^10.12.0",
39
+ "prettier": "^3.6.2"
40
+ },
41
+ "keywords": [
42
+ "nodejs",
43
+ "javascript",
44
+ "cli",
45
+ "developer-tools",
46
+ "logger",
47
+ "logging",
48
+ "console",
49
+ "json",
50
+ "log-levels",
51
+ "dog"
52
+ ]
53
+ }
package/src/index.js CHANGED
@@ -1,80 +1,101 @@
1
- import { format } from "node:util";
2
- import { levels } from "./levels.js";
3
-
4
- /**
5
- * Create a small logger. Methods return the emitted line, or undefined if filtered.
6
- * @param {{emoji?: boolean, color?: boolean, timestamp?: boolean, json?: boolean, quiet?: boolean, prefix?: string, level?: string, write?: (line: string, level: string) => void, clock?: () => Date}} [options]
7
- */
8
- export function createDogLogger(options = {}) {
9
- if (!options || typeof options !== "object" || Array.isArray(options))
10
- throw new TypeError("Options must be an object.");
11
- const config = {
12
- emoji: true,
13
- color: false,
14
- timestamp: false,
15
- json: false,
16
- quiet: false,
17
- prefix: "",
18
- level: "info",
19
- write: (line, level) =>
20
- level === "warn" || level === "error"
21
- ? console.error(line)
22
- : console.log(line),
23
- clock: () => new Date(),
24
- ...options,
25
- };
26
- for (const key of ["emoji", "color", "timestamp", "json", "quiet"]) {
27
- if (typeof config[key] !== "boolean")
28
- throw new TypeError(`${key} must be a boolean.`);
29
- }
30
- if (typeof config.prefix !== "string")
31
- throw new TypeError("prefix must be a string.");
32
- if (typeof config.level !== "string" || !Object.hasOwn(levels, config.level))
33
- throw new RangeError(
34
- `level must be one of: ${Object.keys(levels).join(", ")}.`,
35
- );
36
- if (typeof config.write !== "function" || typeof config.clock !== "function")
37
- throw new TypeError("write and clock must be functions.");
38
- return Object.fromEntries(
39
- Object.entries(levels).map(([level, style]) => [
40
- level,
41
- (...args) => {
42
- if (config.quiet || style.rank < levels[config.level].rank)
43
- return undefined;
44
- const message = format(...args);
45
- let timestamp;
46
- if (config.timestamp) {
47
- const date = config.clock();
48
- if (!(date instanceof Date) || !Number.isFinite(date.getTime()))
49
- throw new TypeError("clock must return a valid Date.");
50
- timestamp = date.toISOString();
51
- }
52
- let line;
53
- if (config.json) {
54
- line = JSON.stringify({
55
- level,
56
- message,
57
- ...(config.prefix ? { prefix: config.prefix } : {}),
58
- ...(timestamp ? { timestamp } : {}),
59
- });
60
- } else {
61
- line = [
62
- timestamp,
63
- config.prefix,
64
- config.emoji ? style.emoji : undefined,
65
- level.toUpperCase().padEnd(7),
66
- message,
67
- ]
68
- .filter((part) => part !== undefined && part !== "")
69
- .join(" ");
70
- if (config.color) line = `\u001b[${style.color}m${line}\u001b[0m`;
71
- }
72
- config.write(line, level);
73
- return line;
74
- },
75
- ]),
76
- );
77
- }
78
-
79
- /** Default logger: emoji enabled, no timestamp/color, info threshold. */
80
- export const doglog = createDogLogger();
1
+ import { format } from "node:util";
2
+ import { levels } from "./levels.js";
3
+ const barks = {
4
+ debug: "Sniffing for clues.",
5
+ log: "Filed under things I sniffed.",
6
+ info: "Good to know. Good dog to tell you.",
7
+ success: "Treat budget approved.",
8
+ warn: "Suspicious squirrel detected.",
9
+ error: "The dog has fetched the incident report.",
10
+ };
11
+
12
+ /**
13
+ * Create a small logger. Methods return the emitted line, or undefined if filtered.
14
+ * @param {{emoji?: boolean, color?: boolean, timestamp?: boolean, json?: boolean, quiet?: boolean, prefix?: string, level?: string, write?: (line: string, level: string) => void, clock?: () => Date}} [options]
15
+ */
16
+ export function createDogLogger(options = {}) {
17
+ if (!options || typeof options !== "object" || Array.isArray(options))
18
+ throw new TypeError("Options must be an object.");
19
+ const config = {
20
+ emoji: true,
21
+ bark: false,
22
+ color: false,
23
+ timestamp: false,
24
+ json: false,
25
+ quiet: false,
26
+ prefix: "",
27
+ level: "info",
28
+ write: (line, level) =>
29
+ level === "warn" || level === "error"
30
+ ? console.error(line)
31
+ : console.log(line),
32
+ clock: () => new Date(),
33
+ ...options,
34
+ };
35
+ for (const key of ["emoji", "color", "timestamp", "json", "quiet", "bark"]) {
36
+ if (typeof config[key] !== "boolean")
37
+ throw new TypeError(`${key} must be a boolean.`);
38
+ }
39
+ if (typeof config.prefix !== "string")
40
+ throw new TypeError("prefix must be a string.");
41
+ if (typeof config.level !== "string" || !Object.hasOwn(levels, config.level))
42
+ throw new RangeError(
43
+ `level must be one of: ${Object.keys(levels).join(", ")}.`,
44
+ );
45
+ if (typeof config.write !== "function" || typeof config.clock !== "function")
46
+ throw new TypeError("write and clock must be functions.");
47
+ const logger = Object.fromEntries(
48
+ Object.entries(levels).map(([level, style]) => [
49
+ level,
50
+ (...args) => {
51
+ if (config.quiet || style.rank < levels[config.level].rank)
52
+ return undefined;
53
+ const message = format(...args);
54
+ const commentary = config.bark ? barks[level] : undefined;
55
+ let timestamp;
56
+ if (config.timestamp) {
57
+ const date = config.clock();
58
+ if (!(date instanceof Date) || !Number.isFinite(date.getTime()))
59
+ throw new TypeError("clock must return a valid Date.");
60
+ timestamp = date.toISOString();
61
+ }
62
+ let line;
63
+ if (config.json) {
64
+ line = JSON.stringify({
65
+ level,
66
+ message,
67
+ ...(commentary ? { commentary } : {}),
68
+ ...(config.prefix ? { prefix: config.prefix } : {}),
69
+ ...(timestamp ? { timestamp } : {}),
70
+ });
71
+ } else {
72
+ line = [
73
+ timestamp,
74
+ config.prefix,
75
+ config.emoji ? style.emoji : undefined,
76
+ level.toUpperCase().padEnd(7),
77
+ message,
78
+ commentary,
79
+ ]
80
+ .filter((part) => part !== undefined && part !== "")
81
+ .join(" ");
82
+ if (config.color) line = `\u001b[${style.color}m${line}\u001b[0m`;
83
+ }
84
+ config.write(line, level);
85
+ return line;
86
+ },
87
+ ]),
88
+ );
89
+ logger.child = (prefix) => {
90
+ if (typeof prefix !== "string" || !prefix.trim())
91
+ throw new TypeError("Child prefix must be a nonempty string.");
92
+ return createDogLogger({
93
+ ...config,
94
+ prefix: [config.prefix, prefix.trim()].filter(Boolean).join(":"),
95
+ });
96
+ };
97
+ return logger;
98
+ }
99
+
100
+ /** Default logger: emoji enabled, no timestamp/color, info threshold. */
101
+ export const doglog = createDogLogger();
package/src/levels.js CHANGED
@@ -1,8 +1,8 @@
1
- export const levels = {
2
- debug: { rank: 10, emoji: "🔍", color: 90 },
3
- log: { rank: 20, emoji: "🐶", color: 37 },
4
- info: { rank: 20, emoji: "🐶", color: 36 },
5
- success: { rank: 20, emoji: "🐾", color: 32 },
6
- warn: { rank: 30, emoji: "🦴", color: 33 },
7
- error: { rank: 40, emoji: "🚨", color: 31 },
8
- };
1
+ export const levels = {
2
+ debug: { rank: 10, emoji: "🔍", color: 90 },
3
+ log: { rank: 20, emoji: "🐶", color: 37 },
4
+ info: { rank: 20, emoji: "🐶", color: 36 },
5
+ success: { rank: 20, emoji: "🐾", color: 32 },
6
+ warn: { rank: 30, emoji: "🦴", color: 33 },
7
+ error: { rank: 40, emoji: "🚨", color: 31 },
8
+ };