-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
aa96ef4
commit 04010de
Showing
8 changed files
with
353 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Gecut Logger | ||
|
||
Gecut Logger is a flexible and colorful logging tool built to enhance your debugging experience for both Node.js and browser-based JavaScript applications. With environment-aware functionalities and stylish output, Gecut Logger helps you to keep track of your application's behavior in an organized and visually appealing way. | ||
|
||
## Features 🚀 | ||
|
||
- **Environment Compatibility**: Works seamlessly in both Node.js and browser environments. | ||
- **Debug Modes**: Easily toggle debugging on and off with DEV_MODE, taking advantage of the localStorage in browsers and environment variables in Node.js. | ||
- **Color Coding**: A colorful logging experience with auto-rotating colors to distinguish logs in both the browser console and terminal. | ||
- **Structured Logging**: Logs are presented with indices, domains, and scope stylings to make tracing easier. | ||
- **Development Friendly**: Rich debug functions available during development for an in-depth examination of your code. | ||
- **Sub-Loggers**: Create sub-loggers with inherited features from a parent logger to maintain the context during complex application workflows. | ||
|
||
## Installation 📦 | ||
|
||
Install the package using npm: | ||
|
||
```bash | ||
npm install @gecut/logger | ||
``` | ||
|
||
## Usage 🛠️ | ||
|
||
Getting started with Gecut Logger is straightforward: | ||
|
||
```ts | ||
import { GecutLogger } from '@gecut/logger'; | ||
|
||
const logger = new GecutLogger('MyApp'); | ||
|
||
// Log an error with a method and description | ||
logger.error('init', 'INIT_FAIL', 'Initialization failed due to an unknown error'); | ||
|
||
// Warn with additional arguments | ||
logger.warning('loadData', 'INVALID_RESPONSE', 'Data response is invalid', { userId: 1 }); | ||
|
||
// Begin a timed operation (development mode only) | ||
logger.time?.('fetchData'); | ||
// code to fetch data here... | ||
logger.timeEnd?.('fetchData'); | ||
``` | ||
|
||
### Example in Browser 🌐 | ||
|
||
```ts | ||
// Assuming DEV_MODE is enabled in localStorage | ||
const logger = new GecutLogger('UIComponent'); | ||
|
||
// Trace a method call and its arguments | ||
logger.methodArgs?.('render', { items: 5 }); | ||
|
||
// Log a property change | ||
logger.property?.('isVisible', true); | ||
|
||
// Other custom logs | ||
logger.other?.('The component has been successfully rendered'); | ||
``` | ||
|
||
### Example in Node.js 🖥️ | ||
|
||
```ts | ||
const logger = new GecutLogger('Server'); | ||
|
||
// Log an error with detailed information | ||
logger.error('start', 'STARTUP_ERROR', 'Server failed to start on port 3000'); | ||
|
||
// Log a method entry | ||
logger.method?.('handleRequest'); | ||
``` | ||
|
||
### Sub-Logger Creation 🧱 | ||
|
||
```ts | ||
const mainLogger = new GecutLogger('App'); | ||
const dbLogger = mainLogger.sub('Database'); | ||
|
||
dbLogger.error('query', 'QUERY_FAIL', 'Query to the products table failed'); | ||
``` | ||
|
||
## API Documentation 📖 | ||
|
||
### GecutLogger | ||
|
||
- **constructor(domain: string, devMode?: boolean)**: Initializes a new logger instance with a domain namespace and an optional development mode flag. | ||
|
||
### Methods | ||
|
||
- **property(property: string, value: unknown)**: Logs a property change (development mode only). | ||
- **method(method: string)**: Logs a method invocation (development mode only). | ||
- **methodArgs(method: string, args: unknown)**: Logs a method call with its arguments (development mode only). | ||
- **methodFull(method: string, args: unknown, result: unknown)**: Logs a method with arguments and the result (development mode only). | ||
- **other(...args: unknown[])**: Logs any custom information (development mode only). | ||
- **warning(method: string, code: string, desc: string, ...args: unknown[])**: Logs a warning message, with a method reference, warning code, description, and additional arguments. | ||
- **error(method: string, code: string, ...args: unknown[])**: Logs an error message, with a method reference, error code, and additional arguments. | ||
|
||
### Static Methods | ||
|
||
- **sub(domain: string, devMode?: boolean)**: Creates a sub-logger with a specified domain scope and optional development mode flag. | ||
|
||
## Contributing 🤝 | ||
|
||
Your contributions are always welcome! If you have suggestions or find bugs, feel free to submit an issue or pull request on our [GitHub repository](https://github.com/gecut/gecut). | ||
|
||
## License 📄 | ||
|
||
This project is licensed under the MIT License - see the LICENSE file for details. | ||
|
||
Bring some color and structure to your debugging efforts with Gecut Logger! 🎨🔍 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
"name": "@gecut/logger", | ||
"version": "1.2.4", | ||
"type": "module", | ||
"author": { | ||
"name": "S. MohammadMahdi Zamanian", | ||
"email": "[email protected]", | ||
"url": "https://mm25zamanain.ir" | ||
}, | ||
"description": "Fancy colorful console debugger with custom scope written in tiny TypeScript, ES module.", | ||
"keywords": [ | ||
"log", | ||
"logger", | ||
"console", | ||
"debug", | ||
"typescript", | ||
"esm", | ||
"gecut" | ||
], | ||
"license": "MIT", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"main": "logger.js", | ||
"types": "logger.d.ts", | ||
"exports": { | ||
".": { | ||
"default": "./logger.js", | ||
"types": "./logger.d.ts" | ||
} | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/gecut/hybrid-core", | ||
"directory": "packages/logger" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/gecut/hybrid-core/issues" | ||
}, | ||
"dependencies": { | ||
"@gecut/utilities": "workspace:^" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import {NODE_MODE} from './core'; | ||
|
||
export const colors = { | ||
browsers: { | ||
RED: '#EF5350', | ||
PINK: '#F06292', | ||
PURPLE: '#AB47BC', | ||
DEEP_PURPLE: '#7E57C2', | ||
INDIGO: '#5C6BC0', | ||
BLUE: '#42A5F5', | ||
LIGHT_BLUE: '#03A9F4', | ||
CYAN: '#26C6DA', | ||
TEAL: '#009688', | ||
GREEN: '#4CAF50', | ||
LIGHT_GREEN: '#8BC34A', | ||
LIME: '#CDDC39', | ||
YELLOW: '#FDD835', | ||
AMBER: '#FFC107', | ||
ORANGE: '#FF9800', | ||
}, | ||
node: ['0;36', '0;35', '0;34', '0;33', '0;32'], | ||
}; | ||
|
||
const colorsList = NODE_MODE ? colors.node : Object.values(colors.browsers); | ||
let colorIndex = 0; | ||
|
||
export function getColor(): string { | ||
const color = colorsList[colorIndex]; | ||
|
||
colorIndex++; | ||
|
||
if (colorIndex >= colorsList.length) { | ||
colorIndex = 0; | ||
} | ||
|
||
return color; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import {isNode} from '@gecut/utilities/browser-or-node.js'; | ||
import {env} from '@gecut/utilities/env.js'; | ||
|
||
export const NODE_MODE = isNode(); | ||
|
||
export const DEV_MODE = | ||
(NODE_MODE === false ? localStorage?.getItem('DEBUG') ?? '0' : env('DEBUG', '0', 'string')) === '1'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
/* eslint-disable max-len */ | ||
import {getColor} from './color-manager'; | ||
import {DEV_MODE, NODE_MODE} from './core'; | ||
|
||
let globalIndex = 0; | ||
|
||
export class GecutLogger { | ||
constructor(domain: string, devMode = DEV_MODE) { | ||
this.domain = GecutLogger.stabilizeDomain(domain); | ||
this.devMode = devMode; | ||
this.style = GecutLogger.style.scope.replaceAll('{{color}}', getColor()); | ||
|
||
this.index = ++globalIndex; | ||
|
||
this.initial(); | ||
|
||
if (DEV_MODE) { | ||
this.initialDevelopments(); | ||
} | ||
} | ||
|
||
private static keySection = NODE_MODE ? '%s%s%s%s%s' : '%c%s%c%s%c'; | ||
private static style = { | ||
scope: NODE_MODE ? '\x1b[{{color}}m' : 'color: {{color}};', | ||
reset: NODE_MODE ? '\x1b[0m' : 'color: inherit;', | ||
dim: NODE_MODE ? '\x1b[2m' : 'color:#888;', | ||
}; | ||
|
||
index: number; | ||
domain: string; | ||
devMode: boolean; | ||
style: string; | ||
|
||
property?: (property: string, value: unknown) => void; | ||
method?: (method: string) => void; | ||
methodArgs?: (method: string, args: unknown) => void; | ||
methodFull?: (method: string, args: unknown, result: unknown) => void; | ||
other?: (...args: unknown[]) => void; | ||
|
||
warning!: (method: string, code: string, desc: string, ...args: unknown[]) => void; | ||
error!: (method: string, code: string, ...args: unknown[]) => void; | ||
|
||
time?: (label: string) => void; | ||
timeEnd?: (label: string) => void; | ||
|
||
sub(domain: string, _devMode = this.devMode) { | ||
return new GecutLogger(`${this.domain} ⬅️ ${domain}`, _devMode); | ||
} | ||
|
||
private static stabilizeDomain(domain: string): string { | ||
domain = domain.trim(); | ||
|
||
const first = domain.charAt(0); | ||
|
||
if (first !== '[' && first !== '{' && first !== '<') { | ||
domain = `[${domain}]`; | ||
} | ||
|
||
return domain; | ||
} | ||
|
||
private initial() { | ||
this.error = NODE_MODE | ||
? console.error.bind( | ||
console, | ||
`${GecutLogger.style.dim}[${this.index}] ${this.style}❌ \n%s\x1b[31m.%s() Error \`%s\`${GecutLogger.style.reset}\n`, | ||
this.domain, | ||
) | ||
: console.error.bind(console, '%c%s%c.%s() Error `%s`\n', this.style, this.domain, GecutLogger.style.reset); | ||
|
||
this.warning = NODE_MODE | ||
? console.warn.bind( | ||
console, | ||
`${GecutLogger.style.dim}[${this.index}] ${this.style}⚠️ \n%s\x1b[33m.%s() Accident \`%s\` %s!${GecutLogger.style.reset}`, | ||
this.domain, | ||
) | ||
: console.warn.bind(console, '%c%s%c.%s() Warn `%s` %s!', this.style, this.domain, GecutLogger.style.reset); | ||
} | ||
|
||
private initialDevelopments() { | ||
this.time = (label: string) => console.time(`[${this.index}] ${this.domain} ${label} duration`); | ||
|
||
this.timeEnd = (label: string) => console.timeEnd(`[${this.index}] ${this.domain} ${label} duration`); | ||
|
||
this.property = console.debug.bind( | ||
console, | ||
`${GecutLogger.keySection}.%s = %o;`, | ||
GecutLogger.style.dim, | ||
`[${this.index}] `, | ||
this.style, | ||
this.domain, | ||
GecutLogger.style.reset, | ||
); | ||
|
||
this.method = console.debug.bind( | ||
console, | ||
`${GecutLogger.keySection}.%s();`, | ||
GecutLogger.style.dim, | ||
`[${this.index}] `, | ||
this.style, | ||
this.domain, | ||
GecutLogger.style.reset, | ||
); | ||
|
||
this.methodArgs = console.debug.bind( | ||
console, | ||
`${GecutLogger.keySection}.%s(%o);`, | ||
GecutLogger.style.dim, | ||
`[${this.index}] `, | ||
this.style, | ||
this.domain, | ||
GecutLogger.style.reset, | ||
); | ||
|
||
this.methodFull = console.debug.bind( | ||
console, | ||
`${GecutLogger.keySection}.%s(%o) => %o`, | ||
GecutLogger.style.dim, | ||
`[${this.index}] `, | ||
this.style, | ||
this.domain, | ||
GecutLogger.style.reset, | ||
); | ||
|
||
this.other = console.debug.bind( | ||
console, | ||
GecutLogger.keySection, | ||
GecutLogger.style.dim, | ||
`[${this.index}] `, | ||
this.style, | ||
this.domain, | ||
GecutLogger.style.reset, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"extends": "../../tsconfig.base", | ||
"compilerOptions": { | ||
"composite": true, | ||
"tsBuildInfoFile": ".tsbuildinfo", | ||
"rootDir": "src", | ||
"outDir": "." | ||
}, | ||
|
||
"include": ["src/**/*.ts"], | ||
"exclude": [], | ||
"references": [{"path": "../utilities"}] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters