hierarchical-area-logger 0.2.9 → 0.3.1

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.
@@ -0,0 +1,57 @@
1
+ type Details = {
2
+ service: string;
3
+ } & Record<string, unknown>;
4
+ type Method = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head' | 'options' | 'trace' | 'connect';
5
+ type LogEntryType = 'info' | 'warn' | 'error' | 'log' | 'debug';
6
+ type LogEntry = {
7
+ type: LogEntryType;
8
+ message: string;
9
+ payload?: object;
10
+ timestamp: number;
11
+ };
12
+ type RootPayload = {
13
+ path?: string;
14
+ method?: Method;
15
+ eventId: string;
16
+ parentEventId?: string;
17
+ details: Details;
18
+ };
19
+ type LogData = Record<string, LogEntry[]>;
20
+ interface LoggerOptions {
21
+ details: Details;
22
+ path?: string;
23
+ parentEventId?: string;
24
+ withParentEventId?: boolean;
25
+ method?: Method;
26
+ overrideEventId?: string;
27
+ defaultArea?: string;
28
+ }
29
+
30
+ declare class Logger {
31
+ eventId: string;
32
+ private log;
33
+ parentEventId?: string;
34
+ private defaultArea;
35
+ constructor(options: LoggerOptions);
36
+ private finalizeRootMessage;
37
+ private addMessage;
38
+ getArea(name?: string): {
39
+ info: (message: string, payload?: LogEntry["payload"]) => void;
40
+ warn: (message: string, payload?: LogEntry["payload"]) => void;
41
+ error: (message: string, payload?: LogEntry["payload"] | Error) => void;
42
+ log: (message: string, payload?: LogEntry["payload"]) => void;
43
+ debug: (message: string, payload?: LogEntry["payload"]) => void;
44
+ };
45
+ dump(): LogData;
46
+ dumpProduction(): LogData;
47
+ appendLogData(logData: LogData): void;
48
+ }
49
+ declare const createLogger: (options: LoggerOptions) => Logger;
50
+
51
+ declare const prettyError: (err: Error) => {
52
+ message: string;
53
+ stack: string[];
54
+ };
55
+
56
+ export { Logger, createLogger, prettyError };
57
+ export type { Details, LogData, LogEntry, LogEntryType, RootPayload };
package/dist/index.d.ts CHANGED
@@ -53,4 +53,5 @@ declare const prettyError: (err: Error) => {
53
53
  stack: string[];
54
54
  };
55
55
 
56
- export { type Details, type LogData, type LogEntry, type LogEntryType, Logger, type RootPayload, createLogger, prettyError };
56
+ export { Logger, createLogger, prettyError };
57
+ export type { Details, LogData, LogEntry, LogEntryType, RootPayload };
@@ -1,8 +1,6 @@
1
- // src/Logger.ts
2
- import { init } from "@paralleldrive/cuid2";
1
+ import { init } from '@paralleldrive/cuid2';
3
2
 
4
- // src/utils.ts
5
- var prettyStack = (stack) => {
3
+ const prettyStack = (stack) => {
6
4
  if (!stack) return [];
7
5
  let toReplace = "";
8
6
  const regex = /file:\/\/\/(.*)(\.wrangler|node_modules)\/.*\)/gm;
@@ -12,12 +10,12 @@ var prettyStack = (stack) => {
12
10
  }
13
11
  return stack.split("\n").map((line) => line.trim()).filter((line) => !line.startsWith("Error: ")).map((line) => line.replace(toReplace, "")).map((line) => line.replace("file://", ""));
14
12
  };
15
- var prettyError = (err) => {
13
+ const prettyError = (err) => {
16
14
  const stack = prettyStack(err.stack);
17
15
  const message = err.message;
18
16
  return { message, stack };
19
17
  };
20
- var createRootLogEntry = ({
18
+ const createRootLogEntry = ({
21
19
  path,
22
20
  method,
23
21
  details,
@@ -51,7 +49,7 @@ var createRootLogEntry = ({
51
49
  }
52
50
  return rootLogEntry;
53
51
  };
54
- var removeEmptyAreas = (logData) => {
52
+ const removeEmptyAreas = (logData) => {
55
53
  const newLogData = {};
56
54
  for (const [key, value] of Object.entries(logData)) {
57
55
  if (value.length > 0) {
@@ -60,10 +58,10 @@ var removeEmptyAreas = (logData) => {
60
58
  }
61
59
  return newLogData;
62
60
  };
63
- var excludeDebugLogs = (logEntries) => {
61
+ const excludeDebugLogs = (logEntries) => {
64
62
  return logEntries.filter((entry) => entry.type !== "debug");
65
63
  };
66
- var processProductionLogData = (logData) => {
64
+ const processProductionLogData = (logData) => {
67
65
  const newLogData = {};
68
66
  for (const [key, value] of Object.entries(logData)) {
69
67
  if (key !== "root") {
@@ -73,8 +71,11 @@ var processProductionLogData = (logData) => {
73
71
  return removeEmptyAreas(newLogData);
74
72
  };
75
73
 
76
- // src/Logger.ts
77
- var Logger = class {
74
+ class Logger {
75
+ eventId;
76
+ log;
77
+ parentEventId;
78
+ defaultArea;
78
79
  constructor(options) {
79
80
  this.parentEventId = options.parentEventId;
80
81
  this.eventId = options.overrideEventId || init({ fingerprint: options.details.service })();
@@ -138,13 +139,10 @@ var Logger = class {
138
139
  delete logData.root;
139
140
  this.log = { ...logData, ...this.log };
140
141
  }
141
- };
142
- var createLogger = (options) => {
142
+ }
143
+ const createLogger = (options) => {
143
144
  return new Logger(options);
144
145
  };
145
- export {
146
- Logger,
147
- createLogger,
148
- prettyError
149
- };
150
- //# sourceMappingURL=index.js.map
146
+
147
+ export { Logger, createLogger, prettyError };
148
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/utils.ts","../src/Logger.ts"],"sourcesContent":["import {\n CreateRootLogEntryOptions,\n LogData,\n LogEntry,\n RootPayload,\n} from './types';\n\nexport const prettyStack = (stack?: string): string[] => {\n if (!stack) return [];\n let toReplace = '';\n\n const regex = /file:\\/\\/\\/(.*)(\\.wrangler|node_modules)\\/.*\\)/gm;\n const m = regex.exec(stack);\n\n if (m && m.length > 1) {\n toReplace = m[1];\n }\n\n return stack\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => !line.startsWith('Error: '))\n .map((line) => line.replace(toReplace, ''))\n .map((line) => line.replace('file://', ''));\n};\n\nexport const prettyError = (err: Error) => {\n const stack = prettyStack(err.stack);\n const message = err.message;\n return { message, stack };\n};\n\nexport const createRootLogEntry = ({\n path,\n method,\n details,\n eventId,\n parentEventId,\n withParentEventId,\n}: CreateRootLogEntryOptions): LogData => {\n const url = new URL(`http://example.com${path ?? '/'}`);\n\n const rootLogEntry: LogData = {\n root: [\n {\n type: 'info',\n message: 'Request received',\n payload: {\n path: `${url.pathname}${url.search}`,\n method,\n details,\n eventId,\n ...(parentEventId && { parentEventId }),\n } as RootPayload,\n timestamp: Date.now(),\n },\n ],\n };\n\n if (withParentEventId && !parentEventId) {\n rootLogEntry.root.push({\n type: 'error',\n message: 'Parent event ID expected but not found',\n timestamp: Date.now(),\n });\n }\n\n return rootLogEntry;\n};\n\nexport const removeEmptyAreas = (logData: LogData) => {\n const newLogData: LogData = {};\n for (const [key, value] of Object.entries(logData)) {\n if (value.length > 0) {\n newLogData[key] = value;\n }\n }\n return newLogData;\n};\n\nexport const excludeDebugLogs = (logEntries: LogEntry[]) => {\n return logEntries.filter((entry) => entry.type !== 'debug');\n};\n\nexport const processProductionLogData = (logData: LogData) => {\n const newLogData: LogData = {};\n for (const [key, value] of Object.entries(logData)) {\n if (key !== 'root') {\n newLogData[key] = excludeDebugLogs(value);\n }\n }\n return removeEmptyAreas(newLogData);\n};\n","import { init } from '@paralleldrive/cuid2';\nimport {\n createRootLogEntry,\n prettyError,\n processProductionLogData,\n} from './utils';\nimport type { LogData, LoggerOptions, LogEntry, LogEntryType } from './types';\n\nexport class Logger {\n public eventId: string;\n private log: LogData;\n public parentEventId?: string;\n private defaultArea: string;\n\n constructor(options: LoggerOptions) {\n this.parentEventId = options.parentEventId;\n this.eventId =\n options.overrideEventId ||\n init({ fingerprint: options.details.service })();\n this.defaultArea = options.defaultArea || 'defaultArea';\n\n this.log = createRootLogEntry({\n path: options.path || '/',\n method: options.method,\n details: options.details,\n eventId: this.eventId,\n parentEventId: options.parentEventId,\n withParentEventId: options.withParentEventId,\n });\n }\n\n private finalizeRootMessage() {\n this.addMessage('root', 'info', 'Request completed', {\n totalDuration: Date.now() - this.log.root[0].timestamp,\n });\n }\n\n private addMessage(\n name: string,\n type: LogEntryType,\n message: string,\n payload?: LogEntry['payload'] | Error\n ) {\n const finalPayload =\n payload instanceof Error ? prettyError(payload) : payload;\n\n this.log[name]!.push({\n type,\n message,\n payload: finalPayload,\n timestamp: Date.now(),\n });\n }\n\n // Area function that returns area-specific logger methods\n public getArea(name = this.defaultArea) {\n if (!this.log[name]) {\n this.log[name] = [];\n }\n\n return {\n info: (message: string, payload?: LogEntry['payload']) => {\n this.addMessage(name, 'info', message, payload);\n },\n warn: (message: string, payload?: LogEntry['payload']) => {\n this.addMessage(name, 'warn', message, payload);\n },\n error: (message: string, payload?: LogEntry['payload'] | Error) => {\n this.addMessage(name, 'error', message, payload);\n },\n log: (message: string, payload?: LogEntry['payload']) => {\n this.addMessage(name, 'log', message, payload);\n },\n debug: (message: string, payload?: LogEntry['payload']) => {\n this.addMessage(name, 'debug', message, payload);\n },\n };\n }\n\n // Public methods on main instance\n public dump(): LogData {\n this.finalizeRootMessage();\n return this.log;\n }\n\n public dumpProduction(): LogData {\n this.finalizeRootMessage();\n return processProductionLogData(this.log);\n }\n\n public appendLogData(logData: LogData): void {\n delete logData.root;\n this.log = { ...logData, ...this.log };\n }\n}\n\n// Factory function for convenience\nexport const createLogger = (options: LoggerOptions): Logger => {\n return new Logger(options);\n};\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,21 @@
1
1
  {
2
2
  "name": "hierarchical-area-logger",
3
- "version": "0.2.9",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
- "main": "dist/index.js",
5
+ "main": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.mjs",
11
+ "default": "./dist/index.mjs"
12
+ }
13
+ },
7
14
  "scripts": {
8
15
  "prepare": "husky",
9
- "build": "tsup",
10
- "dev": "tsup --watch",
16
+ "build": "unbuild",
17
+ "dev": "unbuild --stub",
18
+ "prepack": "unbuild",
11
19
  "test": "vitest",
12
20
  "test:ui": "vitest --ui",
13
21
  "coverage": "vitest --coverage",
@@ -34,18 +42,21 @@
34
42
  "engines": {
35
43
  "node": ">=18.0.0"
36
44
  },
45
+ "files": [
46
+ "dist"
47
+ ],
37
48
  "description": "Hierarchical Area Logger",
38
49
  "devDependencies": {
39
- "@eslint/js": "^9.0.0",
40
- "@typescript-eslint/eslint-plugin": "^8.0.0",
41
- "@typescript-eslint/parser": "^8.0.0",
42
- "@vitest/coverage-v8": "^4.0.18",
43
- "eslint": "^9.0.0",
50
+ "@eslint/js": "^9.39.5",
51
+ "@typescript-eslint/eslint-plugin": "^8.63.0",
52
+ "@typescript-eslint/parser": "^8.63.0",
53
+ "@vitest/coverage-v8": "^4.1.10",
54
+ "eslint": "^10.7.0",
44
55
  "husky": "^9.1.7",
45
- "prettier": "^3.8.1",
46
- "tsup": "^8.5.1",
47
- "typescript": "^5.0.0",
48
- "vitest": "^4.0.18"
56
+ "prettier": "^3.9.5",
57
+ "typescript": "^6.0.3",
58
+ "unbuild": "^3.6.1",
59
+ "vitest": "^4.1.10"
49
60
  },
50
61
  "dependencies": {
51
62
  "@paralleldrive/cuid2": "^3.0.6"
package/.husky/pre-commit DELETED
@@ -1,2 +0,0 @@
1
- npm run format
2
- npm run lint
package/.prettierignore DELETED
@@ -1,4 +0,0 @@
1
- node_modules
2
- dist
3
- coverage
4
- *.log
package/.prettierrc DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "semi": true,
3
- "trailingComma": "es5",
4
- "singleQuote": true,
5
- "printWidth": 80,
6
- "tabWidth": 2,
7
- "useTabs": false
8
- }
@@ -1,73 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- education, socio-economic status, nationality, personal appearance, race,
10
- religion, or sexual identity and orientation.
11
-
12
- ## Our Standards
13
-
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
16
-
17
- - Using welcoming and inclusive language
18
- - Being respectful of differing viewpoints and experiences
19
- - Gracefully accepting constructive criticism
20
- - Focusing on what is best for the community
21
- - Showing empathy towards other community members
22
-
23
- Examples of unacceptable behavior by participants include:
24
-
25
- - The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- - Trolling, insulting/derogatory comments, and personal or political attacks
28
- - Public or private harassment
29
- - Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
31
- - Other conduct which could reasonably be considered inappropriate in a
32
- professional setting
33
-
34
- ## Our Responsibilities
35
-
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
39
-
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
45
-
46
- ## Scope
47
-
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
54
-
55
- ## Enforcement
56
-
57
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at {{ email }}. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
63
-
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
67
-
68
- ## Attribution
69
-
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72
-
73
- [homepage]: https://www.contributor-covenant.org
package/CONTRIBUTING.md DELETED
@@ -1,313 +0,0 @@
1
- # 🤝 Contributing to Hierarchical Area Logger
2
-
3
- Thank you for your interest in contributing to this TypeScript logging library! This guide will help you get started and ensure your contributions align with the project standards.
4
-
5
- ## 📋 Table of Contents
6
-
7
- - [Development Setup](#development-setup)
8
- - [Development Workflow](#development-workflow)
9
- - [Project Structure](#project-structure)
10
- - [Code Standards](#code-standards)
11
- - [Testing](#testing)
12
- - [Pull Request Process](#pull-request-process)
13
- - [Release Process](#release-process)
14
-
15
- ## 🛠 Development Setup
16
-
17
- ### Prerequisites
18
-
19
- - **Node.js** (v18 or higher)
20
- - **npm** or **yarn** package manager
21
- - **TypeScript** knowledge
22
-
23
- ### Installation
24
-
25
- 1. **Fork and clone the repository**
26
-
27
- ```bash
28
- git clone https://github.com/Em3ODMe/hierarchical-area-logger.git
29
- cd hierarchical-area-logger
30
- ```
31
-
32
- 2. **Install dependencies**
33
-
34
- ```bash
35
- npm install
36
- ```
37
-
38
- 3. **Verify setup**
39
- ```bash
40
- npm run lint:check
41
- npm test
42
- npm run build
43
- ```
44
-
45
- ## 🔄 Development Workflow
46
-
47
- ### Available Scripts
48
-
49
- | Script | Purpose | When to Use |
50
- | ------------------ | ------------------------ | ------------------ |
51
- | `npm run dev` | Watch mode development | Active development |
52
- | `npm run build` | Build the library | Before committing |
53
- | `npm test` | Run unit tests | After code changes |
54
- | `npm run test:ui` | Interactive test runner | Debugging tests |
55
- | `npm run lint` | Check code quality | Before committing |
56
- | `npm run lint:fix` | Auto-fix lint issues | During development |
57
- | `npm run coverage` | Generate coverage report | Before PR |
58
-
59
- ### Daily Development
60
-
61
- 1. **Start development server**
62
-
63
- ```bash
64
- npm run dev
65
- ```
66
-
67
- 2. **Make changes to source files** in `src/` directory
68
-
69
- 3. **Run tests frequently**
70
-
71
- ```bash
72
- npm test
73
- ```
74
-
75
- 4. **Check linting**
76
-
77
- ```bash
78
- npm run lint:check
79
- ```
80
-
81
- 5. **Build before commit**
82
- ```bash
83
- npm run build
84
- ```
85
-
86
- ## 📁 Project Structure
87
-
88
- ```
89
- logger/
90
- ├── src/
91
- │ ├── index.ts # Main entry point and exports
92
- │ ├── Logger.ts # Core Logger class implementation
93
- │ ├── types.ts # TypeScript type definitions
94
- │ └── utils.ts # Utility functions
95
- ├── dist/ # Built output (auto-generated)
96
- ├── test/
97
- │ └── logger.test.ts # Test suite
98
- ├── coverage/ # Coverage reports (auto-generated)
99
- ├── package.json # Project configuration
100
- ├── tsconfig.json # TypeScript configuration
101
- ├── vitest.config.ts # Test configuration
102
- ├── eslint.config.js # Linting configuration
103
- └── tsup.config.ts # Build configuration
104
- ```
105
-
106
- ### Key Files & Responsibilities
107
-
108
- - **`src/Logger.ts`**: Core Logger class with area-based logging
109
- - **`src/types.ts`**: TypeScript interfaces and type definitions
110
- - **`src/utils.ts`**: Helper functions for log creation and error handling
111
- - **`src/index.ts`**: Public API exports
112
-
113
- ## 📝 Code Standards
114
-
115
- ### TypeScript Configuration
116
-
117
- - **Target**: ES2020
118
- - **Module**: ESNext
119
- - **Strict mode**: Enabled
120
- - **Output**: Both CommonJS and ESM modules
121
-
122
- ### ESLint Rules
123
-
124
- Key rules enforced:
125
-
126
- - No unused variables (with `_` prefix exception)
127
- - Warn on `any` types
128
- - Prefer `const` over `let`
129
- - No `var` declarations
130
- - No empty functions (warn)
131
-
132
- ### Code Style Guidelines
133
-
134
- 1. **Use TypeScript for all new code**
135
- 2. **Follow existing naming conventions** (camelCase for variables, PascalCase for classes)
136
- 3. **Export only what's necessary** from index.ts
137
- 4. **Add JSDoc comments for public APIs**
138
- 5. **Use meaningful variable and function names**
139
-
140
- ### Import Organization
141
-
142
- ```typescript
143
- // External dependencies
144
- import { init } from '@paralleldrive/cuid2';
145
-
146
- // Internal modules
147
- import { createRootLogEntry, prettyError } from './utils';
148
- import { LogData, LoggerOptions, LogEntry } from './types';
149
- ```
150
-
151
- ## 🧪 Testing
152
-
153
- ### Test Framework
154
-
155
- - **Vitest** for unit testing
156
- - **Coverage** with v8 provider
157
- - **100% coverage requirement** for new code
158
-
159
- ### Writing Tests
160
-
161
- 1. **Test file location**: `test/` directory
162
- 2. **Naming convention**: `*.test.ts`
163
- 3. **Structure your tests**:
164
-
165
- ```typescript
166
- import { describe, it, expect } from 'vitest';
167
- import { createLogger } from '../src/index';
168
-
169
- describe('Logger functionality', () => {
170
- it('should create logger with event ID', () => {
171
- const logger = createLogger({
172
- details: { service: 'test' },
173
- });
174
-
175
- expect(logger.eventId).toBeDefined();
176
- expect(typeof logger.eventId).toBe('string');
177
- });
178
- });
179
- ```
180
-
181
- ### Test Categories
182
-
183
- 1. **Unit tests**: Individual function behavior
184
- 2. **Integration tests**: Component interaction
185
- 3. **Edge cases**: Error handling, invalid inputs
186
- 4. **Type safety**: TypeScript compilation checks
187
-
188
- ## 🔄 Pull Request Process
189
-
190
- ### Branch Naming
191
-
192
- Use descriptive branch names:
193
-
194
- - `feature/area-logging-enhancement`
195
- - `fix/error-handling-bug`
196
- - `docs/updated-readme`
197
-
198
- ### Commit Messages
199
-
200
- Follow conventional commits:
201
-
202
- ```
203
- type(scope): description
204
-
205
- feat(logger): add batch logging capability
206
- fix(types): resolve optional parameter issue
207
- docs(readme): update installation instructions
208
- ```
209
-
210
- ### Before Submitting PR
211
-
212
- 1. **Create feature branch** from main
213
- 2. **Make your changes** with atomic commits
214
- 3. **Ensure all tests pass**:
215
- ```bash
216
- npm test
217
- npm run test
218
- ```
219
- 4. **Verify linting**:
220
- ```bash
221
- npm run lint:check
222
- ```
223
- 5. **Build successfully**:
224
- ```bash
225
- npm run build
226
- ```
227
- 6. **Update documentation** if needed
228
-
229
- ### PR Description Template
230
-
231
- ```markdown
232
- ## Description
233
-
234
- Brief description of changes made.
235
-
236
- ## Type of Change
237
-
238
- - [ ] Bug fix
239
- - [ ] New feature
240
- - [ ] Breaking change
241
- - [ ] Documentation update
242
-
243
- ## Testing
244
-
245
- - [ ] All tests pass
246
- - [ ] 100% coverage maintained
247
- - [ ] New tests added for new functionality
248
-
249
- ## Checklist
250
-
251
- - [ ] Code follows project style guidelines
252
- - [ ] Self-review completed
253
- - [ ] Documentation updated if necessary
254
- ```
255
-
256
- ## 🚀 Release Process
257
-
258
- ### Version Management
259
-
260
- - Follow **Semantic Versioning** (SemVer)
261
- - Update version in `package.json`
262
- - Create git tag for releases
263
-
264
- ### Pre-release Checks
265
-
266
- 1. **All tests pass**
267
- 2. **100% coverage maintained**
268
- 3. **Linting passes**
269
- 4. **Build succeeds**
270
- 5. **Documentation updated**
271
-
272
- ### Build Verification
273
-
274
- ```bash
275
- # Clean build
276
- rm -rf dist/
277
- npm run build
278
-
279
- # Verify outputs
280
- ls -la dist/
281
- # Should contain: index.js, index.mjs, index.d.ts, source maps
282
- ```
283
-
284
- ### Publishing
285
-
286
- 1. **Update version** in package.json
287
- 2. **Create git tag**:
288
- ```bash
289
- git tag v0.1.1
290
- git push origin v0.1.1
291
- ```
292
- 3. **Publish to npm** (if you have access):
293
- ```bash
294
- npm publish
295
- ```
296
-
297
- ## 🆘 Getting Help
298
-
299
- - **Check existing issues** for similar problems
300
- - **Read the README.md** for usage examples
301
- - **Look at test files** for implementation patterns
302
- - **Review TypeScript types** in `src/types.ts`
303
-
304
- ## 📚 Additional Resources
305
-
306
- - [TypeScript Handbook](https://www.typescriptlang.org/docs/)
307
- - [Vitest Documentation](https://vitest.dev/)
308
- - [ESLint Configuration](https://eslint.org/docs/latest/)
309
- - [Semantic Versioning](https://semver.org/)
310
-
311
- ---
312
-
313
- Thank you for contributing to the Hierarchical Area Logger project! Your contributions help make this library better for everyone. 🎉
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/Logger.ts","../src/utils.ts"],"sourcesContent":["import { init } from '@paralleldrive/cuid2';\nimport {\n createRootLogEntry,\n prettyError,\n processProductionLogData,\n} from './utils';\nimport type { LogData, LoggerOptions, LogEntry, LogEntryType } from './types';\n\nexport class Logger {\n public eventId: string;\n private log: LogData;\n public parentEventId?: string;\n private defaultArea: string;\n\n constructor(options: LoggerOptions) {\n this.parentEventId = options.parentEventId;\n this.eventId =\n options.overrideEventId ||\n init({ fingerprint: options.details.service })();\n this.defaultArea = options.defaultArea || 'defaultArea';\n\n this.log = createRootLogEntry({\n path: options.path || '/',\n method: options.method,\n details: options.details,\n eventId: this.eventId,\n parentEventId: options.parentEventId,\n withParentEventId: options.withParentEventId,\n });\n }\n\n private finalizeRootMessage() {\n this.addMessage('root', 'info', 'Request completed', {\n totalDuration: Date.now() - this.log.root[0].timestamp,\n });\n }\n\n private addMessage(\n name: string,\n type: LogEntryType,\n message: string,\n payload?: LogEntry['payload'] | Error\n ) {\n const finalPayload =\n payload instanceof Error ? prettyError(payload) : payload;\n\n this.log[name]!.push({\n type,\n message,\n payload: finalPayload,\n timestamp: Date.now(),\n });\n }\n\n // Area function that returns area-specific logger methods\n public getArea(name = this.defaultArea) {\n if (!this.log[name]) {\n this.log[name] = [];\n }\n\n return {\n info: (message: string, payload?: LogEntry['payload']) => {\n this.addMessage(name, 'info', message, payload);\n },\n warn: (message: string, payload?: LogEntry['payload']) => {\n this.addMessage(name, 'warn', message, payload);\n },\n error: (message: string, payload?: LogEntry['payload'] | Error) => {\n this.addMessage(name, 'error', message, payload);\n },\n log: (message: string, payload?: LogEntry['payload']) => {\n this.addMessage(name, 'log', message, payload);\n },\n debug: (message: string, payload?: LogEntry['payload']) => {\n this.addMessage(name, 'debug', message, payload);\n },\n };\n }\n\n // Public methods on main instance\n public dump(): LogData {\n this.finalizeRootMessage();\n return this.log;\n }\n\n public dumpProduction(): LogData {\n this.finalizeRootMessage();\n return processProductionLogData(this.log);\n }\n\n public appendLogData(logData: LogData): void {\n delete logData.root;\n this.log = { ...logData, ...this.log };\n }\n}\n\n// Factory function for convenience\nexport const createLogger = (options: LoggerOptions): Logger => {\n return new Logger(options);\n};\n","import {\n CreateRootLogEntryOptions,\n LogData,\n LogEntry,\n RootPayload,\n} from './types';\n\nexport const prettyStack = (stack?: string): string[] => {\n if (!stack) return [];\n let toReplace = '';\n\n const regex = /file:\\/\\/\\/(.*)(\\.wrangler|node_modules)\\/.*\\)/gm;\n const m = regex.exec(stack);\n\n if (m && m.length > 1) {\n toReplace = m[1];\n }\n\n return stack\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => !line.startsWith('Error: '))\n .map((line) => line.replace(toReplace, ''))\n .map((line) => line.replace('file://', ''));\n};\n\nexport const prettyError = (err: Error) => {\n const stack = prettyStack(err.stack);\n const message = err.message;\n return { message, stack };\n};\n\nexport const createRootLogEntry = ({\n path,\n method,\n details,\n eventId,\n parentEventId,\n withParentEventId,\n}: CreateRootLogEntryOptions): LogData => {\n const url = new URL(`http://example.com${path ?? '/'}`);\n\n const rootLogEntry: LogData = {\n root: [\n {\n type: 'info',\n message: 'Request received',\n payload: {\n path: `${url.pathname}${url.search}`,\n method,\n details,\n eventId,\n ...(parentEventId && { parentEventId }),\n } as RootPayload,\n timestamp: Date.now(),\n },\n ],\n };\n\n if (withParentEventId && !parentEventId) {\n rootLogEntry.root.push({\n type: 'error',\n message: 'Parent event ID expected but not found',\n timestamp: Date.now(),\n });\n }\n\n return rootLogEntry;\n};\n\nexport const removeEmptyAreas = (logData: LogData) => {\n const newLogData: LogData = {};\n for (const [key, value] of Object.entries(logData)) {\n if (value.length > 0) {\n newLogData[key] = value;\n }\n }\n return newLogData;\n};\n\nexport const excludeDebugLogs = (logEntries: LogEntry[]) => {\n return logEntries.filter((entry) => entry.type !== 'debug');\n};\n\nexport const processProductionLogData = (logData: LogData) => {\n const newLogData: LogData = {};\n for (const [key, value] of Object.entries(logData)) {\n if (key !== 'root') {\n newLogData[key] = excludeDebugLogs(value);\n }\n }\n return removeEmptyAreas(newLogData);\n};\n"],"mappings":"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","names":[]}
package/eslint.config.js DELETED
@@ -1,43 +0,0 @@
1
- import js from '@eslint/js';
2
- import tseslint from '@typescript-eslint/eslint-plugin';
3
- import tsparser from '@typescript-eslint/parser';
4
-
5
- export default [
6
- js.configs.recommended,
7
- {
8
- files: ['**/*.ts'],
9
- languageOptions: {
10
- parser: tsparser,
11
- ecmaVersion: 2020,
12
- sourceType: 'module',
13
- globals: {
14
- process: 'readonly',
15
- Buffer: 'readonly',
16
- __dirname: 'readonly',
17
- __filename: 'readonly',
18
- console: 'readonly',
19
- URL: 'readonly',
20
- URLSearchParams: 'readonly',
21
- },
22
- },
23
- plugins: {
24
- '@typescript-eslint': tseslint,
25
- },
26
- rules: {
27
- ...tseslint.configs.recommended.rules,
28
- '@typescript-eslint/no-unused-vars': [
29
- 'error',
30
- { argsIgnorePattern: '^_' },
31
- ],
32
- '@typescript-eslint/explicit-function-return-type': 'off',
33
- '@typescript-eslint/no-explicit-any': 'warn',
34
- '@typescript-eslint/no-empty-function': 'warn',
35
- 'prefer-const': 'error',
36
- 'no-var': 'error',
37
- 'no-console': 'off',
38
- },
39
- },
40
- {
41
- ignores: ['dist/', 'node_modules/', '*.js'],
42
- },
43
- ];
package/src/Logger.ts DELETED
@@ -1,100 +0,0 @@
1
- import { init } from '@paralleldrive/cuid2';
2
- import {
3
- createRootLogEntry,
4
- prettyError,
5
- processProductionLogData,
6
- } from './utils';
7
- import type { LogData, LoggerOptions, LogEntry, LogEntryType } from './types';
8
-
9
- export class Logger {
10
- public eventId: string;
11
- private log: LogData;
12
- public parentEventId?: string;
13
- private defaultArea: string;
14
-
15
- constructor(options: LoggerOptions) {
16
- this.parentEventId = options.parentEventId;
17
- this.eventId =
18
- options.overrideEventId ||
19
- init({ fingerprint: options.details.service })();
20
- this.defaultArea = options.defaultArea || 'defaultArea';
21
-
22
- this.log = createRootLogEntry({
23
- path: options.path || '/',
24
- method: options.method,
25
- details: options.details,
26
- eventId: this.eventId,
27
- parentEventId: options.parentEventId,
28
- withParentEventId: options.withParentEventId,
29
- });
30
- }
31
-
32
- private finalizeRootMessage() {
33
- this.addMessage('root', 'info', 'Request completed', {
34
- totalDuration: Date.now() - this.log.root[0].timestamp,
35
- });
36
- }
37
-
38
- private addMessage(
39
- name: string,
40
- type: LogEntryType,
41
- message: string,
42
- payload?: LogEntry['payload'] | Error
43
- ) {
44
- const finalPayload =
45
- payload instanceof Error ? prettyError(payload) : payload;
46
-
47
- this.log[name]!.push({
48
- type,
49
- message,
50
- payload: finalPayload,
51
- timestamp: Date.now(),
52
- });
53
- }
54
-
55
- // Area function that returns area-specific logger methods
56
- public getArea(name = this.defaultArea) {
57
- if (!this.log[name]) {
58
- this.log[name] = [];
59
- }
60
-
61
- return {
62
- info: (message: string, payload?: LogEntry['payload']) => {
63
- this.addMessage(name, 'info', message, payload);
64
- },
65
- warn: (message: string, payload?: LogEntry['payload']) => {
66
- this.addMessage(name, 'warn', message, payload);
67
- },
68
- error: (message: string, payload?: LogEntry['payload'] | Error) => {
69
- this.addMessage(name, 'error', message, payload);
70
- },
71
- log: (message: string, payload?: LogEntry['payload']) => {
72
- this.addMessage(name, 'log', message, payload);
73
- },
74
- debug: (message: string, payload?: LogEntry['payload']) => {
75
- this.addMessage(name, 'debug', message, payload);
76
- },
77
- };
78
- }
79
-
80
- // Public methods on main instance
81
- public dump(): LogData {
82
- this.finalizeRootMessage();
83
- return this.log;
84
- }
85
-
86
- public dumpProduction(): LogData {
87
- this.finalizeRootMessage();
88
- return processProductionLogData(this.log);
89
- }
90
-
91
- public appendLogData(logData: LogData): void {
92
- delete logData.root;
93
- this.log = { ...logData, ...this.log };
94
- }
95
- }
96
-
97
- // Factory function for convenience
98
- export const createLogger = (options: LoggerOptions): Logger => {
99
- return new Logger(options);
100
- };
package/src/index.ts DELETED
@@ -1,9 +0,0 @@
1
- export { Logger, createLogger } from './Logger';
2
- export type {
3
- LogData,
4
- LogEntry,
5
- LogEntryType,
6
- Details,
7
- RootPayload,
8
- } from './types';
9
- export { prettyError } from './utils';
package/src/types.ts DELETED
@@ -1,42 +0,0 @@
1
- export type Details = { service: string } & Record<string, unknown>;
2
- export type Method =
3
- | 'get'
4
- | 'post'
5
- | 'put'
6
- | 'delete'
7
- | 'patch'
8
- | 'head'
9
- | 'options'
10
- | 'trace'
11
- | 'connect';
12
-
13
- export type LogEntryType = 'info' | 'warn' | 'error' | 'log' | 'debug';
14
-
15
- export type LogEntry = {
16
- type: LogEntryType;
17
- message: string;
18
- payload?: object;
19
- timestamp: number;
20
- };
21
- export type RootPayload = {
22
- path?: string;
23
- method?: Method;
24
- eventId: string;
25
- parentEventId?: string;
26
- details: Details;
27
- };
28
- export type CreateRootLogEntryOptions = RootPayload & {
29
- path?: string;
30
- withParentEventId?: boolean;
31
- };
32
- export type LogData = Record<string, LogEntry[]>;
33
-
34
- export interface LoggerOptions {
35
- details: Details;
36
- path?: string;
37
- parentEventId?: string;
38
- withParentEventId?: boolean;
39
- method?: Method;
40
- overrideEventId?: string;
41
- defaultArea?: string;
42
- }
package/src/utils.ts DELETED
@@ -1,93 +0,0 @@
1
- import {
2
- CreateRootLogEntryOptions,
3
- LogData,
4
- LogEntry,
5
- RootPayload,
6
- } from './types';
7
-
8
- export const prettyStack = (stack?: string): string[] => {
9
- if (!stack) return [];
10
- let toReplace = '';
11
-
12
- const regex = /file:\/\/\/(.*)(\.wrangler|node_modules)\/.*\)/gm;
13
- const m = regex.exec(stack);
14
-
15
- if (m && m.length > 1) {
16
- toReplace = m[1];
17
- }
18
-
19
- return stack
20
- .split('\n')
21
- .map((line) => line.trim())
22
- .filter((line) => !line.startsWith('Error: '))
23
- .map((line) => line.replace(toReplace, ''))
24
- .map((line) => line.replace('file://', ''));
25
- };
26
-
27
- export const prettyError = (err: Error) => {
28
- const stack = prettyStack(err.stack);
29
- const message = err.message;
30
- return { message, stack };
31
- };
32
-
33
- export const createRootLogEntry = ({
34
- path,
35
- method,
36
- details,
37
- eventId,
38
- parentEventId,
39
- withParentEventId,
40
- }: CreateRootLogEntryOptions): LogData => {
41
- const url = new URL(`http://example.com${path ?? '/'}`);
42
-
43
- const rootLogEntry: LogData = {
44
- root: [
45
- {
46
- type: 'info',
47
- message: 'Request received',
48
- payload: {
49
- path: `${url.pathname}${url.search}`,
50
- method,
51
- details,
52
- eventId,
53
- ...(parentEventId && { parentEventId }),
54
- } as RootPayload,
55
- timestamp: Date.now(),
56
- },
57
- ],
58
- };
59
-
60
- if (withParentEventId && !parentEventId) {
61
- rootLogEntry.root.push({
62
- type: 'error',
63
- message: 'Parent event ID expected but not found',
64
- timestamp: Date.now(),
65
- });
66
- }
67
-
68
- return rootLogEntry;
69
- };
70
-
71
- export const removeEmptyAreas = (logData: LogData) => {
72
- const newLogData: LogData = {};
73
- for (const [key, value] of Object.entries(logData)) {
74
- if (value.length > 0) {
75
- newLogData[key] = value;
76
- }
77
- }
78
- return newLogData;
79
- };
80
-
81
- export const excludeDebugLogs = (logEntries: LogEntry[]) => {
82
- return logEntries.filter((entry) => entry.type !== 'debug');
83
- };
84
-
85
- export const processProductionLogData = (logData: LogData) => {
86
- const newLogData: LogData = {};
87
- for (const [key, value] of Object.entries(logData)) {
88
- if (key !== 'root') {
89
- newLogData[key] = excludeDebugLogs(value);
90
- }
91
- }
92
- return removeEmptyAreas(newLogData);
93
- };
package/tsconfig.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "ESNext",
5
- "lib": ["ES2020", "dom"],
6
- "declaration": true,
7
- "outDir": "./dist",
8
- "rootDir": "./src",
9
- "strict": true,
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "forceConsistentCasingInFileNames": true,
13
- "moduleResolution": "node",
14
- "allowSyntheticDefaultImports": true,
15
- "resolveJsonModule": true
16
- },
17
- "include": ["src/**/*"],
18
- "exclude": ["node_modules", "dist"]
19
- }
package/tsup.config.ts DELETED
@@ -1,11 +0,0 @@
1
- import { defineConfig } from 'tsup';
2
-
3
- export default defineConfig({
4
- entry: ['src/index.ts'],
5
- format: ['esm'],
6
- dts: true,
7
- clean: true,
8
- sourcemap: true,
9
- splitting: false,
10
- minify: false,
11
- });
package/vitest.config.ts DELETED
@@ -1,8 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig({
4
- test: {
5
- globals: true,
6
- environment: 'node',
7
- },
8
- });