kailogger 1.0.0-dark.red
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 +86 -0
- package/dist/core/Logger.d.ts +20 -0
- package/dist/core/Logger.js +85 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +19 -0
- package/dist/styles/gradients.d.ts +29 -0
- package/dist/styles/gradients.js +29 -0
- package/dist/styles/palettes.d.ts +26 -0
- package/dist/styles/palettes.js +28 -0
- package/dist/utils/spinner.d.ts +10 -0
- package/dist/utils/spinner.js +46 -0
- package/examples/demo.ts +28 -0
- package/package.json +21 -0
- package/src/core/Logger.ts +81 -0
- package/src/index.ts +3 -0
- package/src/styles/gradients.ts +22 -0
- package/src/styles/palettes.ts +27 -0
- package/src/utils/spinner.ts +39 -0
- package/tsconfig.json +20 -0
package/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# 🌸 KaiLogger
|
|
2
|
+
|
|
3
|
+
> The most **divine**, **beautiful**, and **elegant** logger for Node.js.
|
|
4
|
+
> Experience logging like never before with mesmerizing gradients, smooth animations, and a developer experience that feels like Zen.
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- » **Divine Gradients**: Make your logs pop with stunning, automatically applied color gradients.
|
|
13
|
+
- » **Beautiful Themes**: Switch between `Zen` (Nature), `Neon` (Cyberpunk), and `Pastel` (Soft) modes.
|
|
14
|
+
- » **Smooth Animations**: Built-in loading spinners that just work.
|
|
15
|
+
- » **High Performance**: Minimal overhead, maximum beauty.
|
|
16
|
+
- » **TypeScript Native**: Fully typed for a superior developer experience.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install kailogger
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
Using KaiLogger is as simple as breathing.
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { kai } from 'kailogger';
|
|
30
|
+
|
|
31
|
+
// 🌿 Standard Logging
|
|
32
|
+
kai.success('Database connected successfully');
|
|
33
|
+
kai.info('Server started on port 3000');
|
|
34
|
+
kai.warning('Memory usage is slightly elevated');
|
|
35
|
+
kai.error('Connection to Redis failed');
|
|
36
|
+
kai.debug('User payload received');
|
|
37
|
+
|
|
38
|
+
// 🌀 Loading Animations
|
|
39
|
+
kai.await('Connecting to the quantum realm...');
|
|
40
|
+
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
kai.stop('Connection established!');
|
|
43
|
+
// or kai.stop() to just clear the spinner
|
|
44
|
+
}, 2000);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Themes
|
|
48
|
+
|
|
49
|
+
Match your mood or your terminal's aesthetic.
|
|
50
|
+
|
|
51
|
+
### **Zen Mode** (Default)
|
|
52
|
+
Calming greens, blues, and nature-inspired gradients.
|
|
53
|
+
```typescript
|
|
54
|
+
kai.setTheme('zen');
|
|
55
|
+
kai.info('Nature is efficient.');
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### **Neon Mode**
|
|
59
|
+
High-contrast, cyberpunk-inspired bright colors.
|
|
60
|
+
```typescript
|
|
61
|
+
kai.setTheme('neon');
|
|
62
|
+
kai.info('System override active.');
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### **Pastel Mode**
|
|
66
|
+
Soft, easy-on-the-eyes colors for a gentle experience.
|
|
67
|
+
```typescript
|
|
68
|
+
kai.setTheme('pastel');
|
|
69
|
+
kai.info('Soft cloud computing.');
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## API Reference
|
|
73
|
+
|
|
74
|
+
- » `kai.success(msg)`: Log a success message.
|
|
75
|
+
- » `kai.error(msg)`: Log an error message.
|
|
76
|
+
- » `kai.warning(msg)`: Log a warning.
|
|
77
|
+
- » `kai.info(msg)`: Log an info message.
|
|
78
|
+
- » `kai.debug(msg)`: Log a debug message.
|
|
79
|
+
- » `kai.log(msg)`: detailed log without level badge.
|
|
80
|
+
- » `kai.box(title, msg)`: Print a message inside a beautiful box.
|
|
81
|
+
- » `kai.await(msg)`: Start a loading spinner.
|
|
82
|
+
- » `kai.stop(msg?)`: Stop the spinner (optional: replace with a success message).
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
MIT © Soblend
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ThemeName } from '../styles/palettes';
|
|
2
|
+
export declare class KaiLogger {
|
|
3
|
+
theme: ThemeName;
|
|
4
|
+
private spinner;
|
|
5
|
+
constructor(theme?: ThemeName);
|
|
6
|
+
setTheme(theme: ThemeName): void;
|
|
7
|
+
private getTime;
|
|
8
|
+
private format;
|
|
9
|
+
success(message: string, ...args: any[]): void;
|
|
10
|
+
error(message: string, ...args: any[]): void;
|
|
11
|
+
warning(message: string, ...args: any[]): void;
|
|
12
|
+
info(message: string, ...args: any[]): void;
|
|
13
|
+
debug(message: string, ...args: any[]): void;
|
|
14
|
+
log(message: string): void;
|
|
15
|
+
box(title: string, message: string): void;
|
|
16
|
+
await(message: string): void;
|
|
17
|
+
stop(message?: string): void;
|
|
18
|
+
private stopSpinner;
|
|
19
|
+
}
|
|
20
|
+
export declare const kai: KaiLogger;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.kai = exports.KaiLogger = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const gradients_1 = require("../styles/gradients");
|
|
9
|
+
const spinner_1 = require("../utils/spinner");
|
|
10
|
+
class KaiLogger {
|
|
11
|
+
constructor(theme = 'zen') {
|
|
12
|
+
this.theme = theme;
|
|
13
|
+
this.spinner = new spinner_1.KaiSpinner();
|
|
14
|
+
gradients_1.paint.setTheme(theme);
|
|
15
|
+
}
|
|
16
|
+
setTheme(theme) {
|
|
17
|
+
this.theme = theme;
|
|
18
|
+
gradients_1.paint.setTheme(theme);
|
|
19
|
+
}
|
|
20
|
+
getTime() {
|
|
21
|
+
const date = new Date();
|
|
22
|
+
return chalk_1.default.gray(`[${date.toLocaleTimeString()}]`);
|
|
23
|
+
}
|
|
24
|
+
format(level, message, ...args) {
|
|
25
|
+
const colors = gradients_1.paint.text[level];
|
|
26
|
+
const badge = gradients_1.paint.apply(` ${level.toUpperCase()} `, colors);
|
|
27
|
+
const formattedMsg = gradients_1.paint.apply(message, colors);
|
|
28
|
+
console.log(`${this.getTime()} ${chalk_1.default.bold(badge)} ${message}`, ...args);
|
|
29
|
+
}
|
|
30
|
+
success(message, ...args) {
|
|
31
|
+
this.stopSpinner();
|
|
32
|
+
const colors = gradients_1.paint.text.success;
|
|
33
|
+
console.log(`${this.getTime()} ${gradients_1.paint.apply(' ✔ SUCCESS ', colors)} ${message}`, ...args);
|
|
34
|
+
}
|
|
35
|
+
error(message, ...args) {
|
|
36
|
+
this.stopSpinner();
|
|
37
|
+
const colors = gradients_1.paint.text.error;
|
|
38
|
+
console.log(`${this.getTime()} ${gradients_1.paint.apply(' ✖ ERROR ', colors)} ${message}`, ...args);
|
|
39
|
+
}
|
|
40
|
+
warning(message, ...args) {
|
|
41
|
+
this.stopSpinner();
|
|
42
|
+
const colors = gradients_1.paint.text.warning;
|
|
43
|
+
console.log(`${this.getTime()} ${gradients_1.paint.apply(' ⚠ WARNING ', colors)} ${message}`, ...args);
|
|
44
|
+
}
|
|
45
|
+
info(message, ...args) {
|
|
46
|
+
this.stopSpinner();
|
|
47
|
+
const colors = gradients_1.paint.text.info;
|
|
48
|
+
console.log(`${this.getTime()} ${gradients_1.paint.apply(' ℹ INFO ', colors)} ${message}`, ...args);
|
|
49
|
+
}
|
|
50
|
+
debug(message, ...args) {
|
|
51
|
+
this.stopSpinner();
|
|
52
|
+
const colors = gradients_1.paint.text.debug;
|
|
53
|
+
console.log(`${this.getTime()} ${gradients_1.paint.apply(' ⚙ DEBUG ', colors)} ${message}`, ...args);
|
|
54
|
+
}
|
|
55
|
+
log(message) {
|
|
56
|
+
this.stopSpinner();
|
|
57
|
+
console.log(`${this.getTime()} ${message}`);
|
|
58
|
+
}
|
|
59
|
+
box(title, message) {
|
|
60
|
+
this.stopSpinner();
|
|
61
|
+
const border = gradients_1.paint.apply('─'.repeat(message.length + 4), gradients_1.paint.text.info);
|
|
62
|
+
console.log(border);
|
|
63
|
+
console.log(`${gradients_1.paint.apply(`| ${title} |`, gradients_1.paint.text.info)}`);
|
|
64
|
+
console.log(border);
|
|
65
|
+
console.log(`| ${message} |`);
|
|
66
|
+
console.log(border);
|
|
67
|
+
}
|
|
68
|
+
await(message) {
|
|
69
|
+
this.spinner.start(message, gradients_1.paint.text.info[0]);
|
|
70
|
+
}
|
|
71
|
+
stop(message) {
|
|
72
|
+
this.spinner.stop('✔', message, gradients_1.paint.text.success[1]);
|
|
73
|
+
}
|
|
74
|
+
stopSpinner() {
|
|
75
|
+
// Just ensure no ghost spinner lines if we log something else
|
|
76
|
+
// this.spinner.stop();
|
|
77
|
+
// Actually we don't want to stop it on every log if it's running,
|
|
78
|
+
// but usually logging interrupts the spinner.
|
|
79
|
+
// Ideally usage is: start -> wait -> stop/success/fail.
|
|
80
|
+
// But if user does: start -> info -> stop, the info might break the spinner line.
|
|
81
|
+
// For now, let's keep it simple.
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.KaiLogger = KaiLogger;
|
|
85
|
+
exports.kai = new KaiLogger();
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./core/Logger"), exports);
|
|
18
|
+
__exportStar(require("./styles/palettes"), exports);
|
|
19
|
+
__exportStar(require("./styles/gradients"), exports);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ThemeName } from './palettes';
|
|
2
|
+
export declare class GradientEngine {
|
|
3
|
+
private currentTheme;
|
|
4
|
+
setTheme(theme: ThemeName): void;
|
|
5
|
+
get text(): {
|
|
6
|
+
success: string[];
|
|
7
|
+
error: string[];
|
|
8
|
+
warning: string[];
|
|
9
|
+
info: string[];
|
|
10
|
+
debug: string[];
|
|
11
|
+
light: string;
|
|
12
|
+
dim: string;
|
|
13
|
+
} | {
|
|
14
|
+
success: string[];
|
|
15
|
+
error: string[];
|
|
16
|
+
warning: string[];
|
|
17
|
+
info: string[];
|
|
18
|
+
debug: string[];
|
|
19
|
+
} | {
|
|
20
|
+
success: string[];
|
|
21
|
+
error: string[];
|
|
22
|
+
warning: string[];
|
|
23
|
+
info: string[];
|
|
24
|
+
debug: string[];
|
|
25
|
+
};
|
|
26
|
+
apply(text: string, colors: string[]): string;
|
|
27
|
+
multiline(text: string, colors: string[]): string;
|
|
28
|
+
}
|
|
29
|
+
export declare const paint: GradientEngine;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.paint = exports.GradientEngine = void 0;
|
|
7
|
+
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
8
|
+
const palettes_1 = require("./palettes");
|
|
9
|
+
class GradientEngine {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.currentTheme = 'zen';
|
|
12
|
+
}
|
|
13
|
+
setTheme(theme) {
|
|
14
|
+
if (palettes_1.palettes[theme]) {
|
|
15
|
+
this.currentTheme = theme;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
get text() {
|
|
19
|
+
return palettes_1.palettes[this.currentTheme];
|
|
20
|
+
}
|
|
21
|
+
apply(text, colors) {
|
|
22
|
+
return (0, gradient_string_1.default)(colors)(text);
|
|
23
|
+
}
|
|
24
|
+
multiline(text, colors) {
|
|
25
|
+
return (0, gradient_string_1.default)(colors).multiline(text);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.GradientEngine = GradientEngine;
|
|
29
|
+
exports.paint = new GradientEngine();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare const palettes: {
|
|
2
|
+
zen: {
|
|
3
|
+
success: string[];
|
|
4
|
+
error: string[];
|
|
5
|
+
warning: string[];
|
|
6
|
+
info: string[];
|
|
7
|
+
debug: string[];
|
|
8
|
+
light: string;
|
|
9
|
+
dim: string;
|
|
10
|
+
};
|
|
11
|
+
neon: {
|
|
12
|
+
success: string[];
|
|
13
|
+
error: string[];
|
|
14
|
+
warning: string[];
|
|
15
|
+
info: string[];
|
|
16
|
+
debug: string[];
|
|
17
|
+
};
|
|
18
|
+
pastel: {
|
|
19
|
+
success: string[];
|
|
20
|
+
error: string[];
|
|
21
|
+
warning: string[];
|
|
22
|
+
info: string[];
|
|
23
|
+
debug: string[];
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export type ThemeName = keyof typeof palettes;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.palettes = void 0;
|
|
4
|
+
exports.palettes = {
|
|
5
|
+
zen: {
|
|
6
|
+
success: ['#00b09b', '#96c93d'],
|
|
7
|
+
error: ['#ff416c', '#ff4b2b'],
|
|
8
|
+
warning: ['#f7971e', '#ffd200'],
|
|
9
|
+
info: ['#2193b0', '#6dd5ed'],
|
|
10
|
+
debug: ['#8e2de2', '#4a00e0'],
|
|
11
|
+
light: '#ffffff',
|
|
12
|
+
dim: '#888888'
|
|
13
|
+
},
|
|
14
|
+
neon: {
|
|
15
|
+
success: ['#39FF14', '#00FF00'],
|
|
16
|
+
error: ['#FF00FF', '#FF0099'],
|
|
17
|
+
warning: ['#FFFF00', '#FFD700'],
|
|
18
|
+
info: ['#00FFFF', '#00BFFF'],
|
|
19
|
+
debug: ['#9D00FF', '#7F00FF']
|
|
20
|
+
},
|
|
21
|
+
pastel: {
|
|
22
|
+
success: ['#77DD77', '#55BB55'],
|
|
23
|
+
error: ['#FF6961', '#FF4444'],
|
|
24
|
+
warning: ['#FFB347', '#FF9933'],
|
|
25
|
+
info: ['#AEC6CF', '#88aabb'],
|
|
26
|
+
debug: ['#B39EB5', '#9988aa']
|
|
27
|
+
}
|
|
28
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class KaiSpinner {
|
|
2
|
+
private timer;
|
|
3
|
+
private index;
|
|
4
|
+
private text;
|
|
5
|
+
private colorFn;
|
|
6
|
+
start(text: string, colorHex?: string): void;
|
|
7
|
+
stop(symbol?: string, endText?: string, colorHex?: string): void;
|
|
8
|
+
fail(text: string): void;
|
|
9
|
+
succeed(text: string): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.KaiSpinner = void 0;
|
|
7
|
+
const process_1 = __importDefault(require("process"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
10
|
+
class KaiSpinner {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.timer = null;
|
|
13
|
+
this.index = 0;
|
|
14
|
+
this.text = '';
|
|
15
|
+
this.colorFn = chalk_1.default.cyan;
|
|
16
|
+
}
|
|
17
|
+
start(text, colorHex = '#00FFFF') {
|
|
18
|
+
this.stop();
|
|
19
|
+
this.text = text;
|
|
20
|
+
this.colorFn = chalk_1.default.hex(colorHex);
|
|
21
|
+
process_1.default.stdout.write('\x1B[?25l');
|
|
22
|
+
this.timer = setInterval(() => {
|
|
23
|
+
const frame = frames[this.index = ++this.index % frames.length];
|
|
24
|
+
process_1.default.stdout.write(`\r${this.colorFn(frame)} ${this.text}`);
|
|
25
|
+
}, 80);
|
|
26
|
+
}
|
|
27
|
+
stop(symbol = '✔', endText, colorHex) {
|
|
28
|
+
if (this.timer) {
|
|
29
|
+
clearInterval(this.timer);
|
|
30
|
+
this.timer = null;
|
|
31
|
+
process_1.default.stdout.write('\r\x1B[K');
|
|
32
|
+
process_1.default.stdout.write('\x1B[?25h');
|
|
33
|
+
if (endText) {
|
|
34
|
+
const finalColor = colorHex ? chalk_1.default.hex(colorHex) : this.colorFn;
|
|
35
|
+
console.log(`${finalColor(symbol)} ${endText}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
fail(text) {
|
|
40
|
+
this.stop('✖', text, '#FF0000');
|
|
41
|
+
}
|
|
42
|
+
succeed(text) {
|
|
43
|
+
this.stop('✔', text, '#00FF00');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.KaiSpinner = KaiSpinner;
|
package/examples/demo.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { kai } from '../src';
|
|
2
|
+
|
|
3
|
+
console.log('\n--- Kai (Zen) Mode (Default) ---\n');
|
|
4
|
+
kai.info('This is an info message');
|
|
5
|
+
kai.success('Database connected successfully');
|
|
6
|
+
kai.warning('Memory usage is high');
|
|
7
|
+
kai.error('Connection timed out');
|
|
8
|
+
kai.debug('Variable x = 10');
|
|
9
|
+
|
|
10
|
+
console.log('\n--- Neon Mode ---\n');
|
|
11
|
+
kai.setTheme('neon');
|
|
12
|
+
kai.info('Neon Info');
|
|
13
|
+
kai.success('Neon Success');
|
|
14
|
+
kai.warning('Neon Warning');
|
|
15
|
+
kai.error('Neon Error');
|
|
16
|
+
|
|
17
|
+
console.log('\n--- Pastel Mode ---\n');
|
|
18
|
+
kai.setTheme('pastel');
|
|
19
|
+
kai.info('Pastel Info');
|
|
20
|
+
kai.success('Pastel Success');
|
|
21
|
+
|
|
22
|
+
console.log('\n--- Animation Test ---\n');
|
|
23
|
+
kai.setTheme('zen');
|
|
24
|
+
kai.await('Loading quantum matrix...');
|
|
25
|
+
|
|
26
|
+
setTimeout(() => {
|
|
27
|
+
kai.stop('Matrix loaded!');
|
|
28
|
+
}, 2000);
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kailogger",
|
|
3
|
+
"version": "1.0.0-dark.red",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@types/node": "^25.0.3",
|
|
14
|
+
"ts-node": "^10.9.2",
|
|
15
|
+
"typescript": "^5.9.3"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"chalk": "^4.1.2",
|
|
19
|
+
"gradient-string": "^3.0.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { paint, GradientEngine } from '../styles/gradients';
|
|
3
|
+
import { KaiSpinner } from '../utils/spinner';
|
|
4
|
+
import { ThemeName } from '../styles/palettes';
|
|
5
|
+
|
|
6
|
+
type LogLevel = 'success' | 'error' | 'warning' | 'info' | 'debug';
|
|
7
|
+
export class KaiLogger {
|
|
8
|
+
private spinner = new KaiSpinner();
|
|
9
|
+
constructor(public theme: ThemeName = 'zen') {
|
|
10
|
+
paint.setTheme(theme);
|
|
11
|
+
}
|
|
12
|
+
public setTheme(theme: ThemeName) {
|
|
13
|
+
this.theme = theme;
|
|
14
|
+
paint.setTheme(theme);
|
|
15
|
+
}
|
|
16
|
+
private getTime() {
|
|
17
|
+
const date = new Date();
|
|
18
|
+
return chalk.gray(`[${date.toLocaleTimeString()}]`);
|
|
19
|
+
}
|
|
20
|
+
private format(level: LogLevel, message: string, ...args: any[]) {
|
|
21
|
+
const colors = paint.text[level];
|
|
22
|
+
const badge = paint.apply(` ${level.toUpperCase()} `, colors);
|
|
23
|
+
const formattedMsg = paint.apply(message, colors);
|
|
24
|
+
console.log(`${this.getTime()} ${chalk.bold(badge)} ${message}`, ...args);
|
|
25
|
+
}
|
|
26
|
+
public success(message: string, ...args: any[]) {
|
|
27
|
+
this.stopSpinner();
|
|
28
|
+
const colors = paint.text.success;
|
|
29
|
+
console.log(`${this.getTime()} ${paint.apply(' ✔ SUCCESS ', colors)} ${message}`, ...args);
|
|
30
|
+
}
|
|
31
|
+
public error(message: string, ...args: any[]) {
|
|
32
|
+
this.stopSpinner();
|
|
33
|
+
const colors = paint.text.error;
|
|
34
|
+
console.log(`${this.getTime()} ${paint.apply(' ✖ ERROR ', colors)} ${message}`, ...args);
|
|
35
|
+
}
|
|
36
|
+
public warning(message: string, ...args: any[]) {
|
|
37
|
+
this.stopSpinner();
|
|
38
|
+
const colors = paint.text.warning;
|
|
39
|
+
console.log(`${this.getTime()} ${paint.apply(' ⚠ WARNING ', colors)} ${message}`, ...args);
|
|
40
|
+
}
|
|
41
|
+
public info(message: string, ...args: any[]) {
|
|
42
|
+
this.stopSpinner();
|
|
43
|
+
const colors = paint.text.info;
|
|
44
|
+
console.log(`${this.getTime()} ${paint.apply(' ℹ INFO ', colors)} ${message}`, ...args);
|
|
45
|
+
}
|
|
46
|
+
public debug(message: string, ...args: any[]) {
|
|
47
|
+
this.stopSpinner();
|
|
48
|
+
const colors = paint.text.debug;
|
|
49
|
+
console.log(`${this.getTime()} ${paint.apply(' ⚙ DEBUG ', colors)} ${message}`, ...args);
|
|
50
|
+
}
|
|
51
|
+
public log(message: string) {
|
|
52
|
+
this.stopSpinner();
|
|
53
|
+
console.log(`${this.getTime()} ${message}`);
|
|
54
|
+
}
|
|
55
|
+
public box(title: string, message: string) {
|
|
56
|
+
this.stopSpinner();
|
|
57
|
+
const border = paint.apply('─'.repeat(message.length + 4), paint.text.info);
|
|
58
|
+
console.log(border);
|
|
59
|
+
console.log(`${paint.apply(`| ${title} |`, paint.text.info)}`);
|
|
60
|
+
console.log(border);
|
|
61
|
+
console.log(`| ${message} |`);
|
|
62
|
+
console.log(border);
|
|
63
|
+
}
|
|
64
|
+
public await(message: string) {
|
|
65
|
+
this.spinner.start(message, paint.text.info[0]);
|
|
66
|
+
}
|
|
67
|
+
public stop(message?: string) {
|
|
68
|
+
this.spinner.stop('✔', message, paint.text.success[1]);
|
|
69
|
+
}
|
|
70
|
+
private stopSpinner() {
|
|
71
|
+
// Just ensure no ghost spinner lines if we log something else
|
|
72
|
+
// this.spinner.stop();
|
|
73
|
+
// Actually we don't want to stop it on every log if it's running,
|
|
74
|
+
// but usually logging interrupts the spinner.
|
|
75
|
+
// Ideally usage is: start -> wait -> stop/success/fail.
|
|
76
|
+
// But if user does: start -> info -> stop, the info might break the spinner line.
|
|
77
|
+
// For now, let's keep it simple.
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const kai = new KaiLogger();
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import gradient from 'gradient-string';
|
|
2
|
+
import { palettes, ThemeName } from './palettes';
|
|
3
|
+
|
|
4
|
+
export class GradientEngine {
|
|
5
|
+
private currentTheme: ThemeName = 'zen';
|
|
6
|
+
setTheme(theme: ThemeName) {
|
|
7
|
+
if (palettes[theme]) {
|
|
8
|
+
this.currentTheme = theme;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
get text() {
|
|
12
|
+
return palettes[this.currentTheme];
|
|
13
|
+
}
|
|
14
|
+
apply(text: string, colors: string[]) {
|
|
15
|
+
return gradient(colors)(text);
|
|
16
|
+
}
|
|
17
|
+
multiline(text: string, colors: string[]) {
|
|
18
|
+
return gradient(colors).multiline(text);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const paint = new GradientEngine();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const palettes = {
|
|
2
|
+
zen: {
|
|
3
|
+
success: ['#00b09b', '#96c93d'],
|
|
4
|
+
error: ['#ff416c', '#ff4b2b'],
|
|
5
|
+
warning: ['#f7971e', '#ffd200'],
|
|
6
|
+
info: ['#2193b0', '#6dd5ed'],
|
|
7
|
+
debug: ['#8e2de2', '#4a00e0'],
|
|
8
|
+
light: '#ffffff',
|
|
9
|
+
dim: '#888888'
|
|
10
|
+
},
|
|
11
|
+
neon: {
|
|
12
|
+
success: ['#39FF14', '#00FF00'],
|
|
13
|
+
error: ['#FF00FF', '#FF0099'],
|
|
14
|
+
warning: ['#FFFF00', '#FFD700'],
|
|
15
|
+
info: ['#00FFFF', '#00BFFF'],
|
|
16
|
+
debug: ['#9D00FF', '#7F00FF']
|
|
17
|
+
},
|
|
18
|
+
pastel: {
|
|
19
|
+
success: ['#77DD77', '#55BB55'],
|
|
20
|
+
error: ['#FF6961', '#FF4444'],
|
|
21
|
+
warning: ['#FFB347', '#FF9933'],
|
|
22
|
+
info: ['#AEC6CF', '#88aabb'],
|
|
23
|
+
debug: ['#B39EB5', '#9988aa']
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type ThemeName = keyof typeof palettes;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import process from 'process';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
5
|
+
export class KaiSpinner {
|
|
6
|
+
private timer: NodeJS.Timeout | null = null;
|
|
7
|
+
private index = 0;
|
|
8
|
+
private text = '';
|
|
9
|
+
private colorFn = chalk.cyan;
|
|
10
|
+
start(text: string, colorHex: string = '#00FFFF') {
|
|
11
|
+
this.stop();
|
|
12
|
+
this.text = text;
|
|
13
|
+
this.colorFn = chalk.hex(colorHex);
|
|
14
|
+
process.stdout.write('\x1B[?25l');
|
|
15
|
+
this.timer = setInterval(() => {
|
|
16
|
+
const frame = frames[this.index = ++this.index % frames.length];
|
|
17
|
+
process.stdout.write(`\r${this.colorFn(frame)} ${this.text}`);
|
|
18
|
+
}, 80);
|
|
19
|
+
}
|
|
20
|
+
stop(symbol: string = '✔', endText?: string, colorHex?: string) {
|
|
21
|
+
if (this.timer) {
|
|
22
|
+
clearInterval(this.timer);
|
|
23
|
+
this.timer = null;
|
|
24
|
+
process.stdout.write('\r\x1B[K');
|
|
25
|
+
process.stdout.write('\x1B[?25h');
|
|
26
|
+
if (endText) {
|
|
27
|
+
const finalColor = colorHex ? chalk.hex(colorHex) : this.colorFn;
|
|
28
|
+
console.log(`${finalColor(symbol)} ${endText}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
fail(text: string) {
|
|
33
|
+
this.stop('✖', text, '#FF0000');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
succeed(text: string) {
|
|
37
|
+
this.stop('✔', text, '#00FF00');
|
|
38
|
+
}
|
|
39
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"outDir": "./dist",
|
|
6
|
+
"rootDir": "./src",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"declaration": true
|
|
12
|
+
},
|
|
13
|
+
"include": [
|
|
14
|
+
"src/**/*"
|
|
15
|
+
],
|
|
16
|
+
"exclude": [
|
|
17
|
+
"node_modules",
|
|
18
|
+
"**/*.test.ts"
|
|
19
|
+
]
|
|
20
|
+
}
|