@mihari/logger-tool 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mihari Contributors
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 ADDED
@@ -0,0 +1,49 @@
1
+ # @mihari/logger-tool
2
+
3
+ CLI tool for the mihari log collection library.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @mihari/logger-tool
9
+ ```
10
+
11
+ ## Configuration
12
+
13
+ Set the following environment variables:
14
+
15
+ ```bash
16
+ export MIHARI_TOKEN="your-api-token"
17
+ export MIHARI_ENDPOINT="https://logs.example.com"
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Send a single message
23
+
24
+ ```bash
25
+ mihari send "Deployment completed" --level info
26
+ mihari send "Error detected" --level error
27
+ ```
28
+
29
+ ### Stream logs from stdin
30
+
31
+ ```bash
32
+ # Pipe from a file
33
+ tail -f /var/log/app.log | mihari tail
34
+
35
+ # Pipe from another command
36
+ my-app 2>&1 | mihari tail --level warn
37
+
38
+ # Pipe from echo
39
+ echo "Quick log message" | mihari tail
40
+ ```
41
+
42
+ ### Options
43
+
44
+ - `--level <level>` - Log level: debug, info, warn, error, fatal (default: info)
45
+ - `--help` - Show help message
46
+
47
+ ## License
48
+
49
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,197 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const readline = __importStar(require("readline"));
38
+ const logger_core_1 = require("@mihari/logger-core");
39
+ const logger_types_1 = require("@mihari/logger-types");
40
+ const USAGE = `
41
+ mihari - CLI tool for mihari log collection
42
+
43
+ Usage:
44
+ mihari send <message> [--level <level>] Send a single log message
45
+ mihari tail Read stdin line by line and send each as a log
46
+
47
+ Environment variables:
48
+ MIHARI_TOKEN Authentication token (required)
49
+ MIHARI_ENDPOINT API endpoint URL (required)
50
+
51
+ Options:
52
+ --level <level> Log level: debug, info, warn, error, fatal (default: info)
53
+ --help Show this help message
54
+
55
+ Examples:
56
+ mihari send "Deployment completed" --level info
57
+ echo "Error occurred" | mihari tail
58
+ tail -f /var/log/app.log | mihari tail --level warn
59
+ `.trim();
60
+ function getConfig() {
61
+ const token = process.env.MIHARI_TOKEN;
62
+ const endpoint = process.env.MIHARI_ENDPOINT;
63
+ if (!token) {
64
+ console.error("Error: MIHARI_TOKEN environment variable is required");
65
+ process.exit(1);
66
+ }
67
+ if (!endpoint) {
68
+ console.error("Error: MIHARI_ENDPOINT environment variable is required");
69
+ process.exit(1);
70
+ }
71
+ return { token, endpoint };
72
+ }
73
+ function parseLevel(levelStr) {
74
+ const normalized = levelStr.toLowerCase();
75
+ const levelMap = {
76
+ debug: logger_types_1.LogLevel.Debug,
77
+ info: logger_types_1.LogLevel.Info,
78
+ warn: logger_types_1.LogLevel.Warn,
79
+ error: logger_types_1.LogLevel.Error,
80
+ fatal: logger_types_1.LogLevel.Fatal,
81
+ };
82
+ const level = levelMap[normalized];
83
+ if (!level) {
84
+ console.error(`Error: Invalid log level "${levelStr}". Valid levels: debug, info, warn, error, fatal`);
85
+ process.exit(1);
86
+ }
87
+ return level;
88
+ }
89
+ async function sendCommand(args) {
90
+ const config = getConfig();
91
+ const client = new logger_core_1.MihariClient(config);
92
+ let message = "";
93
+ let level = logger_types_1.LogLevel.Info;
94
+ const mutableArgs = [...args];
95
+ while (mutableArgs.length > 0) {
96
+ const arg = mutableArgs.shift();
97
+ if (arg === "--level" && mutableArgs.length > 0) {
98
+ level = parseLevel(mutableArgs.shift());
99
+ }
100
+ else if (!message) {
101
+ message = arg;
102
+ }
103
+ }
104
+ if (!message) {
105
+ console.error("Error: Message is required for send command");
106
+ process.exit(1);
107
+ }
108
+ switch (level) {
109
+ case logger_types_1.LogLevel.Debug:
110
+ client.debug(message);
111
+ break;
112
+ case logger_types_1.LogLevel.Info:
113
+ client.info(message);
114
+ break;
115
+ case logger_types_1.LogLevel.Warn:
116
+ client.warn(message);
117
+ break;
118
+ case logger_types_1.LogLevel.Error:
119
+ client.error(message);
120
+ break;
121
+ case logger_types_1.LogLevel.Fatal:
122
+ client.fatal(message);
123
+ break;
124
+ }
125
+ await client.flush();
126
+ console.log(`Sent: [${level}] ${message}`);
127
+ }
128
+ async function tailCommand(args) {
129
+ const config = getConfig();
130
+ const client = new logger_core_1.MihariClient(config);
131
+ let level = logger_types_1.LogLevel.Info;
132
+ const mutableArgs = [...args];
133
+ while (mutableArgs.length > 0) {
134
+ const arg = mutableArgs.shift();
135
+ if (arg === "--level" && mutableArgs.length > 0) {
136
+ level = parseLevel(mutableArgs.shift());
137
+ }
138
+ }
139
+ const rl = readline.createInterface({
140
+ input: process.stdin,
141
+ terminal: false,
142
+ });
143
+ let lineCount = 0;
144
+ rl.on("line", (line) => {
145
+ const trimmed = line.trim();
146
+ if (!trimmed)
147
+ return;
148
+ switch (level) {
149
+ case logger_types_1.LogLevel.Debug:
150
+ client.debug(trimmed);
151
+ break;
152
+ case logger_types_1.LogLevel.Info:
153
+ client.info(trimmed);
154
+ break;
155
+ case logger_types_1.LogLevel.Warn:
156
+ client.warn(trimmed);
157
+ break;
158
+ case logger_types_1.LogLevel.Error:
159
+ client.error(trimmed);
160
+ break;
161
+ case logger_types_1.LogLevel.Fatal:
162
+ client.fatal(trimmed);
163
+ break;
164
+ }
165
+ lineCount++;
166
+ });
167
+ rl.on("close", async () => {
168
+ await client.shutdown();
169
+ console.log(`Sent ${lineCount} log entries`);
170
+ });
171
+ }
172
+ async function main() {
173
+ const args = process.argv.slice(2);
174
+ if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
175
+ console.log(USAGE);
176
+ process.exit(0);
177
+ }
178
+ const command = args[0];
179
+ const commandArgs = args.slice(1);
180
+ switch (command) {
181
+ case "send":
182
+ await sendCommand(commandArgs);
183
+ break;
184
+ case "tail":
185
+ await tailCommand(commandArgs);
186
+ break;
187
+ default:
188
+ console.error(`Unknown command: ${command}`);
189
+ console.log(USAGE);
190
+ process.exit(1);
191
+ }
192
+ }
193
+ main().catch((err) => {
194
+ console.error("Fatal error:", err);
195
+ process.exit(1);
196
+ });
197
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@mihari/logger-tool",
3
+ "version": "0.1.0",
4
+ "description": "CLI tool for mihari log collection",
5
+ "main": "src/index.ts",
6
+ "types": "src/index.ts",
7
+ "bin": {
8
+ "mihari": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "clean": "rm -rf dist",
16
+ "test": "cd ../.. && npx vitest run --config vitest.config.ts packages/tool"
17
+ },
18
+ "devDependencies": {
19
+ "vitest": "^3.0.0"
20
+ },
21
+ "dependencies": {
22
+ "@mihari/logger-core": "^0.1.0",
23
+ "@mihari/logger-types": "^0.1.0"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/mihari/mihari-js",
32
+ "directory": "packages/tool"
33
+ },
34
+ "gitHead": "dc10a3217caa819965eb3a1e2ff3901a16e510aa"
35
+ }
package/src/index.ts ADDED
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+
3
+ import * as readline from "readline";
4
+ import { MihariClient } from "@mihari/logger-core";
5
+ import { LogLevel, MihariConfig } from "@mihari/logger-types";
6
+
7
+ const USAGE = `
8
+ mihari - CLI tool for mihari log collection
9
+
10
+ Usage:
11
+ mihari send <message> [--level <level>] Send a single log message
12
+ mihari tail Read stdin line by line and send each as a log
13
+
14
+ Environment variables:
15
+ MIHARI_TOKEN Authentication token (required)
16
+ MIHARI_ENDPOINT API endpoint URL (required)
17
+
18
+ Options:
19
+ --level <level> Log level: debug, info, warn, error, fatal (default: info)
20
+ --help Show this help message
21
+
22
+ Examples:
23
+ mihari send "Deployment completed" --level info
24
+ echo "Error occurred" | mihari tail
25
+ tail -f /var/log/app.log | mihari tail --level warn
26
+ `.trim();
27
+
28
+ function getConfig(): MihariConfig {
29
+ const token = process.env.MIHARI_TOKEN;
30
+ const endpoint = process.env.MIHARI_ENDPOINT;
31
+
32
+ if (!token) {
33
+ console.error("Error: MIHARI_TOKEN environment variable is required");
34
+ process.exit(1);
35
+ }
36
+
37
+ if (!endpoint) {
38
+ console.error("Error: MIHARI_ENDPOINT environment variable is required");
39
+ process.exit(1);
40
+ }
41
+
42
+ return { token, endpoint };
43
+ }
44
+
45
+ function parseLevel(levelStr: string): LogLevel {
46
+ const normalized = levelStr.toLowerCase();
47
+ const levelMap: Record<string, LogLevel> = {
48
+ debug: LogLevel.Debug,
49
+ info: LogLevel.Info,
50
+ warn: LogLevel.Warn,
51
+ error: LogLevel.Error,
52
+ fatal: LogLevel.Fatal,
53
+ };
54
+
55
+ const level = levelMap[normalized];
56
+ if (!level) {
57
+ console.error(
58
+ `Error: Invalid log level "${levelStr}". Valid levels: debug, info, warn, error, fatal`
59
+ );
60
+ process.exit(1);
61
+ }
62
+
63
+ return level;
64
+ }
65
+
66
+ async function sendCommand(args: readonly string[]): Promise<void> {
67
+ const config = getConfig();
68
+ const client = new MihariClient(config);
69
+
70
+ let message = "";
71
+ let level = LogLevel.Info;
72
+
73
+ const mutableArgs = [...args];
74
+ while (mutableArgs.length > 0) {
75
+ const arg = mutableArgs.shift()!;
76
+ if (arg === "--level" && mutableArgs.length > 0) {
77
+ level = parseLevel(mutableArgs.shift()!);
78
+ } else if (!message) {
79
+ message = arg;
80
+ }
81
+ }
82
+
83
+ if (!message) {
84
+ console.error("Error: Message is required for send command");
85
+ process.exit(1);
86
+ }
87
+
88
+ switch (level) {
89
+ case LogLevel.Debug:
90
+ client.debug(message);
91
+ break;
92
+ case LogLevel.Info:
93
+ client.info(message);
94
+ break;
95
+ case LogLevel.Warn:
96
+ client.warn(message);
97
+ break;
98
+ case LogLevel.Error:
99
+ client.error(message);
100
+ break;
101
+ case LogLevel.Fatal:
102
+ client.fatal(message);
103
+ break;
104
+ }
105
+
106
+ await client.flush();
107
+ console.log(`Sent: [${level}] ${message}`);
108
+ }
109
+
110
+ async function tailCommand(args: readonly string[]): Promise<void> {
111
+ const config = getConfig();
112
+ const client = new MihariClient(config);
113
+
114
+ let level = LogLevel.Info;
115
+
116
+ const mutableArgs = [...args];
117
+ while (mutableArgs.length > 0) {
118
+ const arg = mutableArgs.shift()!;
119
+ if (arg === "--level" && mutableArgs.length > 0) {
120
+ level = parseLevel(mutableArgs.shift()!);
121
+ }
122
+ }
123
+
124
+ const rl = readline.createInterface({
125
+ input: process.stdin,
126
+ terminal: false,
127
+ });
128
+
129
+ let lineCount = 0;
130
+
131
+ rl.on("line", (line: string) => {
132
+ const trimmed = line.trim();
133
+ if (!trimmed) return;
134
+
135
+ switch (level) {
136
+ case LogLevel.Debug:
137
+ client.debug(trimmed);
138
+ break;
139
+ case LogLevel.Info:
140
+ client.info(trimmed);
141
+ break;
142
+ case LogLevel.Warn:
143
+ client.warn(trimmed);
144
+ break;
145
+ case LogLevel.Error:
146
+ client.error(trimmed);
147
+ break;
148
+ case LogLevel.Fatal:
149
+ client.fatal(trimmed);
150
+ break;
151
+ }
152
+
153
+ lineCount++;
154
+ });
155
+
156
+ rl.on("close", async () => {
157
+ await client.shutdown();
158
+ console.log(`Sent ${lineCount} log entries`);
159
+ });
160
+ }
161
+
162
+ async function main(): Promise<void> {
163
+ const args = process.argv.slice(2);
164
+
165
+ if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
166
+ console.log(USAGE);
167
+ process.exit(0);
168
+ }
169
+
170
+ const command = args[0];
171
+ const commandArgs = args.slice(1);
172
+
173
+ switch (command) {
174
+ case "send":
175
+ await sendCommand(commandArgs);
176
+ break;
177
+ case "tail":
178
+ await tailCommand(commandArgs);
179
+ break;
180
+ default:
181
+ console.error(`Unknown command: ${command}`);
182
+ console.log(USAGE);
183
+ process.exit(1);
184
+ }
185
+ }
186
+
187
+ main().catch((err) => {
188
+ console.error("Fatal error:", err);
189
+ process.exit(1);
190
+ });