@happyvertical/logger 0.74.8
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/AGENT.md +33 -0
- package/LICENSE +7 -0
- package/README.md +135 -0
- package/dist/adapter.d.ts +30 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/cli/claude-context.d.ts +3 -0
- package/dist/cli/claude-context.d.ts.map +1 -0
- package/dist/cli/claude-context.js +21 -0
- package/dist/cli/claude-context.js.map +1 -0
- package/dist/console.d.ts +39 -0
- package/dist/console.d.ts.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +155 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +52 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/sentry-adapter.d.ts +45 -0
- package/dist/sentry-adapter.d.ts.map +1 -0
- package/dist/sentry.d.ts +8 -0
- package/dist/sentry.d.ts.map +1 -0
- package/dist/sentry.js +79 -0
- package/dist/sentry.js.map +1 -0
- package/dist/signal-types.d.ts +46 -0
- package/dist/signal-types.d.ts.map +1 -0
- package/dist/test-logger.d.ts +56 -0
- package/dist/test-logger.d.ts.map +1 -0
- package/metadata.json +37 -0
- package/package.json +74 -0
package/AGENT.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# @happyvertical/logger
|
|
2
|
+
|
|
3
|
+
<!-- BEGIN AGENT:GENERATED -->
|
|
4
|
+
## Purpose
|
|
5
|
+
Structured logging for HAVE SDK with signal adapter
|
|
6
|
+
|
|
7
|
+
## Package Map
|
|
8
|
+
- Package: `@happyvertical/logger`
|
|
9
|
+
- Hierarchy path: `@happyvertical/sdk > packages > logger`
|
|
10
|
+
- Workspace position: `18 of 30` local packages
|
|
11
|
+
- Internal dependencies: `@happyvertical/utils`
|
|
12
|
+
- Internal dependents: `@happyvertical/comfyui`, `@happyvertical/email`, `@happyvertical/encryption`, `@happyvertical/messages`, `@happyvertical/social`, `@happyvertical/video`
|
|
13
|
+
- Knowledge graph files: `AGENT.md`, `metadata.json`, `ecosystem-manifest.json`
|
|
14
|
+
|
|
15
|
+
## Build & Test
|
|
16
|
+
```bash
|
|
17
|
+
pnpm --filter @happyvertical/logger build
|
|
18
|
+
pnpm --filter @happyvertical/logger test
|
|
19
|
+
pnpm --filter @happyvertical/logger typecheck
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Agent Correction Loops
|
|
23
|
+
- If module resolution or export errors mention a workspace dependency, build the dependency first (`pnpm --filter @happyvertical/utils build`) and then rerun `pnpm --filter @happyvertical/logger build`.
|
|
24
|
+
- If you hit type-only regressions, run `pnpm --filter @happyvertical/logger typecheck` before rerunning the package build or tests to isolate the failing surface.
|
|
25
|
+
- If failures span multiple packages or Turborepo ordering looks wrong, run `pnpm build` and `pnpm typecheck` from the repo root before retrying package-scoped commands.
|
|
26
|
+
|
|
27
|
+
## Ecosystem Relationships
|
|
28
|
+
- Provides: Structured logging for HAVE SDK with signal adapter
|
|
29
|
+
- Implements: none
|
|
30
|
+
- Requires: @happyvertical/utils, @sentry/node
|
|
31
|
+
- Stability: stable (Primary package surface is described as implemented and production-oriented.)
|
|
32
|
+
<!-- END AGENT:GENERATED -->
|
|
33
|
+
|
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright <2025> <Happy Vertical Corporation>
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# @happyvertical/logger
|
|
2
|
+
|
|
3
|
+
Structured logging for HAVE SDK with signal adapter integration and optional Sentry error tracking. Provides a `Logger` interface with four severity levels, a console implementation with level filtering, and adapters that convert SMRT framework signals into log entries or Sentry breadcrumbs/exceptions.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @happyvertical/logger
|
|
9
|
+
|
|
10
|
+
# Optional: for Sentry integration
|
|
11
|
+
pnpm add @sentry/node
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Depends on `@happyvertical/utils`. Optional peer dependency on `@sentry/node` (for the `/sentry` subpath).
|
|
15
|
+
|
|
16
|
+
## Basic Usage
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { createLogger } from '@happyvertical/logger';
|
|
20
|
+
|
|
21
|
+
// Console logger with default 'info' level
|
|
22
|
+
const logger = createLogger(true);
|
|
23
|
+
|
|
24
|
+
logger.info('Application started');
|
|
25
|
+
logger.debug('Verbose detail'); // Not output (below 'info')
|
|
26
|
+
logger.warn('High memory usage', { memoryMB: 512 });
|
|
27
|
+
logger.error('Connection failed', { host: 'localhost', port: 5432 });
|
|
28
|
+
|
|
29
|
+
// Configure a specific level
|
|
30
|
+
const debugLogger = createLogger({ level: 'debug' });
|
|
31
|
+
|
|
32
|
+
// No-op logger — all calls discarded, zero overhead
|
|
33
|
+
const silent = createLogger(false);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Environment Variable
|
|
37
|
+
|
|
38
|
+
Set `HAVE_LOGGER_LEVEL` to `debug`, `info`, `warn`, or `error`. Applies when using `createLogger(true)` or `createLogger({})`. Explicit config takes precedence:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
process.env.HAVE_LOGGER_LEVEL = 'debug';
|
|
42
|
+
const logger = createLogger(true); // uses 'debug' from env
|
|
43
|
+
|
|
44
|
+
const explicit = createLogger({ level: 'warn' }); // uses 'warn', ignores env
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Log Levels
|
|
48
|
+
|
|
49
|
+
`debug < info < warn < error` — messages below the configured threshold are discarded.
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
const logger = createLogger({ level: 'warn' });
|
|
53
|
+
logger.debug('ignored'); // not output
|
|
54
|
+
logger.info('ignored'); // not output
|
|
55
|
+
logger.warn('output'); // output
|
|
56
|
+
logger.error('output'); // output
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Output format: `[LEVEL] message {"key":"value"}`
|
|
60
|
+
|
|
61
|
+
## Signal Adapter
|
|
62
|
+
|
|
63
|
+
`LoggerAdapter` converts SMRT framework signals into structured log entries:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { createLogger, LoggerAdapter } from '@happyvertical/logger';
|
|
67
|
+
|
|
68
|
+
const logger = createLogger({ level: 'info' });
|
|
69
|
+
const adapter = new LoggerAdapter(logger);
|
|
70
|
+
// Register adapter with a signal bus to log operations automatically
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Signal type mapping: `start` → debug, `step` → debug, `end` → info, `error` → error.
|
|
74
|
+
|
|
75
|
+
## Sentry Adapter
|
|
76
|
+
|
|
77
|
+
The `/sentry` subpath routes signals to Sentry/GlitchTip. Requires `@sentry/node` as a peer dependency.
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { createSentryAdapter } from '@happyvertical/logger/sentry';
|
|
81
|
+
|
|
82
|
+
const adapter = createSentryAdapter({ category: 'myapp' });
|
|
83
|
+
// Register adapter with a signal bus
|
|
84
|
+
|
|
85
|
+
// Error signals → Sentry.captureException with scope tags
|
|
86
|
+
// Non-error signals → Sentry.addBreadcrumb for debugging trail
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## API Overview
|
|
90
|
+
|
|
91
|
+
### Factory
|
|
92
|
+
|
|
93
|
+
| Function | Description |
|
|
94
|
+
|----------|-------------|
|
|
95
|
+
| `createLogger(config)` | Returns a `Logger` — `ConsoleLogger` when enabled, no-op when `false` |
|
|
96
|
+
| `createSentryAdapter(config?)` | Returns a `SentryAdapter` (from `/sentry` subpath) |
|
|
97
|
+
|
|
98
|
+
### Classes
|
|
99
|
+
|
|
100
|
+
| Class | Description |
|
|
101
|
+
|-------|-------------|
|
|
102
|
+
| `ConsoleLogger` | Logger implementation with level filtering, writes to `console.*` |
|
|
103
|
+
| `LoggerAdapter` | Signal adapter that converts signals to structured log messages |
|
|
104
|
+
| `SentryAdapter` | Signal adapter that routes errors to Sentry and adds breadcrumbs |
|
|
105
|
+
|
|
106
|
+
### Types
|
|
107
|
+
|
|
108
|
+
| Type | Description |
|
|
109
|
+
|------|-------------|
|
|
110
|
+
| `Logger` | Interface with `debug`, `info`, `warn`, `error` methods |
|
|
111
|
+
| `LogLevel` | `'debug' \| 'info' \| 'warn' \| 'error'` |
|
|
112
|
+
| `LoggerConfig` | `boolean \| { level?: LogLevel }` |
|
|
113
|
+
| `Signal` | Signal event from operation execution |
|
|
114
|
+
| `SignalAdapter` | Interface for handling signals |
|
|
115
|
+
| `SignalType` | `'start' \| 'step' \| 'end' \| 'error'` |
|
|
116
|
+
| `SentryAdapterConfig` | `{ category?: string }` |
|
|
117
|
+
|
|
118
|
+
### Custom Logger
|
|
119
|
+
|
|
120
|
+
Implement the `Logger` interface for custom backends:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import type { Logger } from '@happyvertical/logger';
|
|
124
|
+
|
|
125
|
+
class MyLogger implements Logger {
|
|
126
|
+
debug(message: string, context?: Record<string, unknown>): void { /* ... */ }
|
|
127
|
+
info(message: string, context?: Record<string, unknown>): void { /* ... */ }
|
|
128
|
+
warn(message: string, context?: Record<string, unknown>): void { /* ... */ }
|
|
129
|
+
error(message: string, context?: Record<string, unknown>): void { /* ... */ }
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Logger } from './logger.js';
|
|
2
|
+
import { Signal, SignalAdapter } from './signal-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Logger Adapter - Converts signals to structured log messages
|
|
5
|
+
*
|
|
6
|
+
* Transforms signals from the SMRT framework into structured log entries.
|
|
7
|
+
* Each signal type is mapped to an appropriate log level:
|
|
8
|
+
* - start → debug
|
|
9
|
+
* - step → debug
|
|
10
|
+
* - end → info
|
|
11
|
+
* - error → error
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const logger = new ConsoleLogger('info');
|
|
16
|
+
* const adapter = new LoggerAdapter(logger);
|
|
17
|
+
* signalBus.register(adapter);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare class LoggerAdapter implements SignalAdapter {
|
|
21
|
+
private logger;
|
|
22
|
+
constructor(logger: Logger);
|
|
23
|
+
/**
|
|
24
|
+
* Handle a signal and log appropriately
|
|
25
|
+
*
|
|
26
|
+
* @param signal - Signal to log
|
|
27
|
+
*/
|
|
28
|
+
handle(signal: Signal): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE/D;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAc,YAAW,aAAa;IACrC,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAElC;;;;OAIG;IACG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CA4D5C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-context.d.ts","sourceRoot":"","sources":["../../src/cli/claude-context.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, mkdirSync, copyFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
const Dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const pkgRoot = join(Dirname, "../..");
|
|
7
|
+
const targetDir = join(process.cwd(), ".claude");
|
|
8
|
+
if (!existsSync(targetDir)) {
|
|
9
|
+
mkdirSync(targetDir, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
const pkgName = "logger";
|
|
12
|
+
const agentMdSrc = existsSync(join(pkgRoot, "AGENT.md")) ? join(pkgRoot, "AGENT.md") : join(pkgRoot, "CLAUDE.md");
|
|
13
|
+
const metaSrc = existsSync(join(pkgRoot, "metadata.json")) ? join(pkgRoot, "metadata.json") : join(pkgRoot, ".claude-meta.json");
|
|
14
|
+
if (existsSync(agentMdSrc)) {
|
|
15
|
+
copyFileSync(agentMdSrc, join(targetDir, `have-${pkgName}.md`));
|
|
16
|
+
}
|
|
17
|
+
if (existsSync(metaSrc)) {
|
|
18
|
+
copyFileSync(metaSrc, join(targetDir, `have-${pkgName}.meta.json`));
|
|
19
|
+
}
|
|
20
|
+
console.log(`✓ Installed @happyvertical/${pkgName} context to .claude/`);
|
|
21
|
+
//# sourceMappingURL=claude-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-context.js","sources":["../../src/cli/claude-context.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI script to install agent context for @happyvertical/logger\n * Run the published context installer binary for this package.\n */\nimport { copyFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst Dirname = dirname(fileURLToPath(import.meta.url));\nconst pkgRoot = join(Dirname, '../..');\nconst targetDir = join(process.cwd(), '.claude');\n\nif (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n}\n\nconst pkgName = 'logger';\nconst agentMdSrc = existsSync(join(pkgRoot, 'AGENT.md'))\n ? join(pkgRoot, 'AGENT.md')\n : join(pkgRoot, 'CLAUDE.md');\nconst metaSrc = existsSync(join(pkgRoot, 'metadata.json'))\n ? join(pkgRoot, 'metadata.json')\n : join(pkgRoot, '.claude-meta.json');\n\nif (existsSync(agentMdSrc)) {\n copyFileSync(agentMdSrc, join(targetDir, `have-${pkgName}.md`));\n}\n\nif (existsSync(metaSrc)) {\n copyFileSync(metaSrc, join(targetDir, `have-${pkgName}.meta.json`));\n}\n\nconsole.log(`✓ Installed @happyvertical/${pkgName} context to .claude/`);\n"],"names":[],"mappings":";;;;AASA,MAAM,UAAU,QAAQ,cAAc,YAAY,GAAG,CAAC;AACtD,MAAM,UAAU,KAAK,SAAS,OAAO;AACrC,MAAM,YAAY,KAAK,QAAQ,IAAA,GAAO,SAAS;AAE/C,IAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,YAAU,WAAW,EAAE,WAAW,KAAA,CAAM;AAC1C;AAEA,MAAM,UAAU;AAChB,MAAM,aAAa,WAAW,KAAK,SAAS,UAAU,CAAC,IACnD,KAAK,SAAS,UAAU,IACxB,KAAK,SAAS,WAAW;AAC7B,MAAM,UAAU,WAAW,KAAK,SAAS,eAAe,CAAC,IACrD,KAAK,SAAS,eAAe,IAC7B,KAAK,SAAS,mBAAmB;AAErC,IAAI,WAAW,UAAU,GAAG;AAC1B,eAAa,YAAY,KAAK,WAAW,QAAQ,OAAO,KAAK,CAAC;AAChE;AAEA,IAAI,WAAW,OAAO,GAAG;AACvB,eAAa,SAAS,KAAK,WAAW,QAAQ,OAAO,YAAY,CAAC;AACpE;AAEA,QAAQ,IAAI,8BAA8B,OAAO,sBAAsB;"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Logger, LogLevel } from './logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Console-based logger with level filtering
|
|
4
|
+
*
|
|
5
|
+
* Logs are written to console with appropriate severity levels.
|
|
6
|
+
* Messages are only output if they meet the configured log level threshold.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const logger = new ConsoleLogger('info');
|
|
11
|
+
* logger.debug('Debug message'); // Not output (below 'info')
|
|
12
|
+
* logger.info('Info message'); // Output
|
|
13
|
+
* logger.error('Error message'); // Output
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare class ConsoleLogger implements Logger {
|
|
17
|
+
private level;
|
|
18
|
+
private static readonly LEVELS;
|
|
19
|
+
constructor(level?: LogLevel);
|
|
20
|
+
/**
|
|
21
|
+
* Check if a log level should be output
|
|
22
|
+
*
|
|
23
|
+
* @param level - Log level to check
|
|
24
|
+
* @returns True if level meets threshold
|
|
25
|
+
*/
|
|
26
|
+
private shouldLog;
|
|
27
|
+
/**
|
|
28
|
+
* Format context for console output
|
|
29
|
+
*
|
|
30
|
+
* @param context - Structured metadata
|
|
31
|
+
* @returns Formatted context string
|
|
32
|
+
*/
|
|
33
|
+
private formatContext;
|
|
34
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
35
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
36
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
37
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=console.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEpD;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAc,YAAW,MAAM;IAQ9B,OAAO,CAAC,KAAK;IAPzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAK5B;gBAEkB,KAAK,GAAE,QAAiB;IAE5C;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAMjB;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAOrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAM/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAM9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAM9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAKhE"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Logger, LoggerConfig } from './logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* @happyvertical/logger - Structured logging for HAVE SDK
|
|
4
|
+
*
|
|
5
|
+
* Provides a structured logging interface with signal adapter integration.
|
|
6
|
+
* Supports configurable log levels and console output.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { createLogger, LoggerAdapter } from '@happyvertical/logger';
|
|
11
|
+
*
|
|
12
|
+
* // Create logger
|
|
13
|
+
* const logger = createLogger({ level: 'info' });
|
|
14
|
+
* logger.info('Application started');
|
|
15
|
+
*
|
|
16
|
+
* // Integrate with signals
|
|
17
|
+
* const adapter = new LoggerAdapter(logger);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export { LoggerAdapter } from './adapter.js';
|
|
21
|
+
export { ConsoleLogger } from './console.js';
|
|
22
|
+
export type { Logger, LoggerConfig, LogLevel } from './logger.js';
|
|
23
|
+
export type { Signal, SignalAdapter, SignalType } from './signal-types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Create a logger from configuration
|
|
26
|
+
*
|
|
27
|
+
* Supports environment variable configuration via HAVE_LOGGER_LEVEL.
|
|
28
|
+
* User-provided options take precedence over environment variables.
|
|
29
|
+
*
|
|
30
|
+
* @param config - Logger configuration (boolean or object)
|
|
31
|
+
* @returns Configured logger instance
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* // Console logger with 'info' level (default)
|
|
36
|
+
* const logger1 = createLogger(true);
|
|
37
|
+
*
|
|
38
|
+
* // Console logger with level from HAVE_LOGGER_LEVEL env var
|
|
39
|
+
* process.env.HAVE_LOGGER_LEVEL = 'debug';
|
|
40
|
+
* const logger2 = createLogger(true); // Uses 'debug' from env
|
|
41
|
+
*
|
|
42
|
+
* // No-op logger (all log calls are discarded)
|
|
43
|
+
* const logger3 = createLogger(false);
|
|
44
|
+
*
|
|
45
|
+
* // Console logger with 'debug' level (overrides env)
|
|
46
|
+
* const logger4 = createLogger({ level: 'debug' });
|
|
47
|
+
*
|
|
48
|
+
* // Custom log level (user options take precedence)
|
|
49
|
+
* process.env.HAVE_LOGGER_LEVEL = 'info';
|
|
50
|
+
* const logger5 = createLogger({ level: 'warn' }); // Uses 'warn' not 'info'
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function createLogger(config: LoggerConfig): Logger;
|
|
54
|
+
/** @internal */
|
|
55
|
+
export declare const PACKAGE_VERSION_INITIALIZED = true;
|
|
56
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAI3E,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAY,MAAM,aAAa,CAAC;AAyBlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CA2BzD;AAED,gBAAgB;AAChB,eAAO,MAAM,2BAA2B,OAAO,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { loadEnvConfig } from "@happyvertical/utils";
|
|
2
|
+
class LoggerAdapter {
|
|
3
|
+
constructor(logger) {
|
|
4
|
+
this.logger = logger;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Handle a signal and log appropriately
|
|
8
|
+
*
|
|
9
|
+
* @param signal - Signal to log
|
|
10
|
+
*/
|
|
11
|
+
async handle(signal) {
|
|
12
|
+
const context = {
|
|
13
|
+
id: signal.id,
|
|
14
|
+
objectId: signal.objectId,
|
|
15
|
+
className: signal.className,
|
|
16
|
+
method: signal.method,
|
|
17
|
+
timestamp: signal.timestamp
|
|
18
|
+
};
|
|
19
|
+
if (signal.duration !== void 0) {
|
|
20
|
+
context.duration = signal.duration;
|
|
21
|
+
}
|
|
22
|
+
if (signal.metadata) {
|
|
23
|
+
context.metadata = signal.metadata;
|
|
24
|
+
}
|
|
25
|
+
switch (signal.type) {
|
|
26
|
+
case "start":
|
|
27
|
+
this.logger.debug(
|
|
28
|
+
`${signal.className}.${signal.method}() started`,
|
|
29
|
+
context
|
|
30
|
+
);
|
|
31
|
+
break;
|
|
32
|
+
case "step":
|
|
33
|
+
this.logger.debug(
|
|
34
|
+
`${signal.className}.${signal.method}() step: ${signal.step || "unknown"}`,
|
|
35
|
+
context
|
|
36
|
+
);
|
|
37
|
+
break;
|
|
38
|
+
case "end":
|
|
39
|
+
this.logger.info(
|
|
40
|
+
`${signal.className}.${signal.method}() completed in ${signal.duration}ms`,
|
|
41
|
+
{
|
|
42
|
+
...context,
|
|
43
|
+
result: signal.result !== void 0 ? "present" : "none"
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
break;
|
|
47
|
+
case "error":
|
|
48
|
+
this.logger.error(
|
|
49
|
+
`${signal.className}.${signal.method}() failed: ${signal.error?.message || "Unknown error"}`,
|
|
50
|
+
{
|
|
51
|
+
...context,
|
|
52
|
+
error: signal.error ? {
|
|
53
|
+
message: signal.error.message,
|
|
54
|
+
name: signal.error.name,
|
|
55
|
+
stack: signal.error.stack
|
|
56
|
+
} : void 0
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
class ConsoleLogger {
|
|
64
|
+
constructor(level = "info") {
|
|
65
|
+
this.level = level;
|
|
66
|
+
}
|
|
67
|
+
static LEVELS = [
|
|
68
|
+
"debug",
|
|
69
|
+
"info",
|
|
70
|
+
"warn",
|
|
71
|
+
"error"
|
|
72
|
+
];
|
|
73
|
+
/**
|
|
74
|
+
* Check if a log level should be output
|
|
75
|
+
*
|
|
76
|
+
* @param level - Log level to check
|
|
77
|
+
* @returns True if level meets threshold
|
|
78
|
+
*/
|
|
79
|
+
shouldLog(level) {
|
|
80
|
+
const currentIndex = ConsoleLogger.LEVELS.indexOf(this.level);
|
|
81
|
+
const messageIndex = ConsoleLogger.LEVELS.indexOf(level);
|
|
82
|
+
return messageIndex >= currentIndex;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Format context for console output
|
|
86
|
+
*
|
|
87
|
+
* @param context - Structured metadata
|
|
88
|
+
* @returns Formatted context string
|
|
89
|
+
*/
|
|
90
|
+
formatContext(context) {
|
|
91
|
+
if (!context || Object.keys(context).length === 0) {
|
|
92
|
+
return "";
|
|
93
|
+
}
|
|
94
|
+
return ` ${JSON.stringify(context)}`;
|
|
95
|
+
}
|
|
96
|
+
debug(message, context) {
|
|
97
|
+
if (this.shouldLog("debug")) {
|
|
98
|
+
console.debug(`[DEBUG] ${message}${this.formatContext(context)}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
info(message, context) {
|
|
102
|
+
if (this.shouldLog("info")) {
|
|
103
|
+
console.info(`[INFO] ${message}${this.formatContext(context)}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
warn(message, context) {
|
|
107
|
+
if (this.shouldLog("warn")) {
|
|
108
|
+
console.warn(`[WARN] ${message}${this.formatContext(context)}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
error(message, context) {
|
|
112
|
+
if (this.shouldLog("error")) {
|
|
113
|
+
console.error(`[ERROR] ${message}${this.formatContext(context)}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
class NoopLogger {
|
|
118
|
+
debug(_message, _context) {
|
|
119
|
+
}
|
|
120
|
+
info(_message, _context) {
|
|
121
|
+
}
|
|
122
|
+
warn(_message, _context) {
|
|
123
|
+
}
|
|
124
|
+
error(_message, _context) {
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function createLogger(config) {
|
|
128
|
+
if (typeof config === "boolean") {
|
|
129
|
+
if (!config) {
|
|
130
|
+
return new NoopLogger();
|
|
131
|
+
}
|
|
132
|
+
const envConfig = loadEnvConfig(
|
|
133
|
+
{},
|
|
134
|
+
{
|
|
135
|
+
packageName: "logger",
|
|
136
|
+
schema: { level: "string" }
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
return new ConsoleLogger(envConfig.level || "info");
|
|
140
|
+
}
|
|
141
|
+
const mergedConfig = loadEnvConfig(config, {
|
|
142
|
+
packageName: "logger",
|
|
143
|
+
schema: { level: "string" }
|
|
144
|
+
});
|
|
145
|
+
const level = mergedConfig.level || "info";
|
|
146
|
+
return new ConsoleLogger(level);
|
|
147
|
+
}
|
|
148
|
+
const PACKAGE_VERSION_INITIALIZED = true;
|
|
149
|
+
export {
|
|
150
|
+
ConsoleLogger,
|
|
151
|
+
LoggerAdapter,
|
|
152
|
+
PACKAGE_VERSION_INITIALIZED,
|
|
153
|
+
createLogger
|
|
154
|
+
};
|
|
155
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/adapter.ts","../src/console.ts","../src/index.ts"],"sourcesContent":["/**\n * Signal adapter for structured logging\n */\n\nimport type { Logger } from './logger.js';\nimport type { Signal, SignalAdapter } from './signal-types.js';\n\n/**\n * Logger Adapter - Converts signals to structured log messages\n *\n * Transforms signals from the SMRT framework into structured log entries.\n * Each signal type is mapped to an appropriate log level:\n * - start → debug\n * - step → debug\n * - end → info\n * - error → error\n *\n * @example\n * ```typescript\n * const logger = new ConsoleLogger('info');\n * const adapter = new LoggerAdapter(logger);\n * signalBus.register(adapter);\n * ```\n */\nexport class LoggerAdapter implements SignalAdapter {\n constructor(private logger: Logger) {}\n\n /**\n * Handle a signal and log appropriately\n *\n * @param signal - Signal to log\n */\n async handle(signal: Signal): Promise<void> {\n const context: Record<string, unknown> = {\n id: signal.id,\n objectId: signal.objectId,\n className: signal.className,\n method: signal.method,\n timestamp: signal.timestamp,\n };\n\n // Add optional fields if present\n if (signal.duration !== undefined) {\n context.duration = signal.duration;\n }\n\n if (signal.metadata) {\n context.metadata = signal.metadata;\n }\n\n switch (signal.type) {\n case 'start':\n this.logger.debug(\n `${signal.className}.${signal.method}() started`,\n context,\n );\n break;\n\n case 'step':\n this.logger.debug(\n `${signal.className}.${signal.method}() step: ${signal.step || 'unknown'}`,\n context,\n );\n break;\n\n case 'end':\n this.logger.info(\n `${signal.className}.${signal.method}() completed in ${signal.duration}ms`,\n {\n ...context,\n result: signal.result !== undefined ? 'present' : 'none',\n },\n );\n break;\n\n case 'error':\n this.logger.error(\n `${signal.className}.${signal.method}() failed: ${signal.error?.message || 'Unknown error'}`,\n {\n ...context,\n error: signal.error\n ? {\n message: signal.error.message,\n name: signal.error.name,\n stack: signal.error.stack,\n }\n : undefined,\n },\n );\n break;\n }\n }\n}\n","/**\n * Console logger implementation with configurable log levels\n */\n\nimport type { Logger, LogLevel } from './logger.js';\n\n/**\n * Console-based logger with level filtering\n *\n * Logs are written to console with appropriate severity levels.\n * Messages are only output if they meet the configured log level threshold.\n *\n * @example\n * ```typescript\n * const logger = new ConsoleLogger('info');\n * logger.debug('Debug message'); // Not output (below 'info')\n * logger.info('Info message'); // Output\n * logger.error('Error message'); // Output\n * ```\n */\nexport class ConsoleLogger implements Logger {\n private static readonly LEVELS: ReadonlyArray<LogLevel> = [\n 'debug',\n 'info',\n 'warn',\n 'error',\n ];\n\n constructor(private level: LogLevel = 'info') {}\n\n /**\n * Check if a log level should be output\n *\n * @param level - Log level to check\n * @returns True if level meets threshold\n */\n private shouldLog(level: LogLevel): boolean {\n const currentIndex = ConsoleLogger.LEVELS.indexOf(this.level);\n const messageIndex = ConsoleLogger.LEVELS.indexOf(level);\n return messageIndex >= currentIndex;\n }\n\n /**\n * Format context for console output\n *\n * @param context - Structured metadata\n * @returns Formatted context string\n */\n private formatContext(context?: Record<string, unknown>): string {\n if (!context || Object.keys(context).length === 0) {\n return '';\n }\n return ` ${JSON.stringify(context)}`;\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n if (this.shouldLog('debug')) {\n console.debug(`[DEBUG] ${message}${this.formatContext(context)}`);\n }\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n if (this.shouldLog('info')) {\n console.info(`[INFO] ${message}${this.formatContext(context)}`);\n }\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n if (this.shouldLog('warn')) {\n console.warn(`[WARN] ${message}${this.formatContext(context)}`);\n }\n }\n\n error(message: string, context?: Record<string, unknown>): void {\n if (this.shouldLog('error')) {\n console.error(`[ERROR] ${message}${this.formatContext(context)}`);\n }\n }\n}\n","/**\n * @happyvertical/logger - Structured logging for HAVE SDK\n *\n * Provides a structured logging interface with signal adapter integration.\n * Supports configurable log levels and console output.\n *\n * @example\n * ```typescript\n * import { createLogger, LoggerAdapter } from '@happyvertical/logger';\n *\n * // Create logger\n * const logger = createLogger({ level: 'info' });\n * logger.info('Application started');\n *\n * // Integrate with signals\n * const adapter = new LoggerAdapter(logger);\n * ```\n */\n\nexport { LoggerAdapter } from './adapter.js';\nexport { ConsoleLogger } from './console.js';\nexport type { Logger, LoggerConfig, LogLevel } from './logger.js';\nexport type { Signal, SignalAdapter, SignalType } from './signal-types.js';\n\nimport { loadEnvConfig } from '@happyvertical/utils';\nimport { ConsoleLogger } from './console.js';\nimport type { Logger, LoggerConfig, LogLevel } from './logger.js';\n\n/**\n * No-op logger that discards all log messages\n *\n * Used when logging is disabled (config: false)\n */\nclass NoopLogger implements Logger {\n debug(_message: string, _context?: Record<string, unknown>): void {\n // No-op\n }\n\n info(_message: string, _context?: Record<string, unknown>): void {\n // No-op\n }\n\n warn(_message: string, _context?: Record<string, unknown>): void {\n // No-op\n }\n\n error(_message: string, _context?: Record<string, unknown>): void {\n // No-op\n }\n}\n\n/**\n * Create a logger from configuration\n *\n * Supports environment variable configuration via HAVE_LOGGER_LEVEL.\n * User-provided options take precedence over environment variables.\n *\n * @param config - Logger configuration (boolean or object)\n * @returns Configured logger instance\n *\n * @example\n * ```typescript\n * // Console logger with 'info' level (default)\n * const logger1 = createLogger(true);\n *\n * // Console logger with level from HAVE_LOGGER_LEVEL env var\n * process.env.HAVE_LOGGER_LEVEL = 'debug';\n * const logger2 = createLogger(true); // Uses 'debug' from env\n *\n * // No-op logger (all log calls are discarded)\n * const logger3 = createLogger(false);\n *\n * // Console logger with 'debug' level (overrides env)\n * const logger4 = createLogger({ level: 'debug' });\n *\n * // Custom log level (user options take precedence)\n * process.env.HAVE_LOGGER_LEVEL = 'info';\n * const logger5 = createLogger({ level: 'warn' }); // Uses 'warn' not 'info'\n * ```\n */\nexport function createLogger(config: LoggerConfig): Logger {\n if (typeof config === 'boolean') {\n // When false, return no-op logger that discards all messages\n if (!config) {\n return new NoopLogger();\n }\n\n // Check HAVE_LOGGER_LEVEL env var when config is true\n const envConfig = loadEnvConfig<{ level?: LogLevel }>(\n {},\n {\n packageName: 'logger',\n schema: { level: 'string' },\n },\n );\n\n return new ConsoleLogger(envConfig.level || 'info');\n }\n\n // Merge user config with env vars (user options take precedence)\n const mergedConfig = loadEnvConfig<{ level?: LogLevel }>(config, {\n packageName: 'logger',\n schema: { level: 'string' },\n });\n\n const level = mergedConfig.level || 'info';\n return new ConsoleLogger(level);\n}\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"names":["ConsoleLogger"],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core logging interfaces and types
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Log levels in order of severity
|
|
6
|
+
*/
|
|
7
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
8
|
+
/**
|
|
9
|
+
* Logger configuration
|
|
10
|
+
* - boolean: true = console logger with 'info' level, false = disabled
|
|
11
|
+
* - object: configure logger with specific level
|
|
12
|
+
*/
|
|
13
|
+
export type LoggerConfig = boolean | {
|
|
14
|
+
level?: LogLevel;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Structured logger interface
|
|
18
|
+
*
|
|
19
|
+
* All methods accept optional context for structured logging.
|
|
20
|
+
* Context should contain machine-readable metadata.
|
|
21
|
+
*/
|
|
22
|
+
export interface Logger {
|
|
23
|
+
/**
|
|
24
|
+
* Log debug message (verbose development information)
|
|
25
|
+
*
|
|
26
|
+
* @param message - Human-readable log message
|
|
27
|
+
* @param context - Optional structured metadata
|
|
28
|
+
*/
|
|
29
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
30
|
+
/**
|
|
31
|
+
* Log informational message (normal operation)
|
|
32
|
+
*
|
|
33
|
+
* @param message - Human-readable log message
|
|
34
|
+
* @param context - Optional structured metadata
|
|
35
|
+
*/
|
|
36
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
37
|
+
/**
|
|
38
|
+
* Log warning message (potential issues)
|
|
39
|
+
*
|
|
40
|
+
* @param message - Human-readable log message
|
|
41
|
+
* @param context - Optional structured metadata
|
|
42
|
+
*/
|
|
43
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
44
|
+
/**
|
|
45
|
+
* Log error message (failures and exceptions)
|
|
46
|
+
*
|
|
47
|
+
* @param message - Human-readable log message
|
|
48
|
+
* @param context - Optional structured metadata
|
|
49
|
+
*/
|
|
50
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG;IAAE,KAAK,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC;AAE1D;;;;;GAKG;AACH,MAAM,WAAW,MAAM;IACrB;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAEhE;;;;;OAKG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAE/D;;;;;OAKG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAE/D;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACjE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Signal, SignalAdapter } from './signal-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the Sentry signal adapter
|
|
4
|
+
*/
|
|
5
|
+
export interface SentryAdapterConfig {
|
|
6
|
+
/** Breadcrumb category (default: 'smrt') */
|
|
7
|
+
category?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Sentry signal adapter — routes SMRT signals to Sentry/GlitchTip
|
|
11
|
+
*
|
|
12
|
+
* Error signals are captured as exceptions with scope tags and context.
|
|
13
|
+
* All other signal types are added as breadcrumbs for debugging trail.
|
|
14
|
+
* Requires `@sentry/node` to be installed and `Sentry.init()` called before use.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { createSentryAdapter } from '@happyvertical/logger/sentry';
|
|
19
|
+
*
|
|
20
|
+
* const adapter = createSentryAdapter({ category: 'myapp' });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare class SentryAdapter implements SignalAdapter {
|
|
24
|
+
private category;
|
|
25
|
+
constructor(config?: SentryAdapterConfig);
|
|
26
|
+
/**
|
|
27
|
+
* Handle a signal by routing to Sentry
|
|
28
|
+
*
|
|
29
|
+
* Error signals are captured as exceptions. All other signal types
|
|
30
|
+
* are added as breadcrumbs.
|
|
31
|
+
*
|
|
32
|
+
* @param signal - The signal to handle
|
|
33
|
+
*/
|
|
34
|
+
handle(signal: Signal): Promise<void>;
|
|
35
|
+
private captureError;
|
|
36
|
+
private addBreadcrumb;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create a Sentry signal adapter
|
|
40
|
+
*
|
|
41
|
+
* @param config - Optional configuration (breadcrumb category)
|
|
42
|
+
* @returns Configured SentryAdapter instance
|
|
43
|
+
*/
|
|
44
|
+
export declare function createSentryAdapter(config?: SentryAdapterConfig): SentryAdapter;
|
|
45
|
+
//# sourceMappingURL=sentry-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry-adapter.d.ts","sourceRoot":"","sources":["../src/sentry-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAc,YAAW,aAAa;IACjD,OAAO,CAAC,QAAQ,CAAS;gBAEb,MAAM,CAAC,EAAE,mBAAmB;IAIxC;;;;;;;OAOG;IACG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3C,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,aAAa;CAqCtB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,CAAC,EAAE,mBAAmB,GAC3B,aAAa,CAEf"}
|
package/dist/sentry.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentry adapter subpath entry point
|
|
3
|
+
*
|
|
4
|
+
* Import via: import { createSentryAdapter } from '@happyvertical/logger/sentry';
|
|
5
|
+
*/
|
|
6
|
+
export type { SentryAdapterConfig } from './sentry-adapter.js';
|
|
7
|
+
export { createSentryAdapter, SentryAdapter } from './sentry-adapter.js';
|
|
8
|
+
//# sourceMappingURL=sentry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry.d.ts","sourceRoot":"","sources":["../src/sentry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/sentry.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as Sentry from "@sentry/node";
|
|
2
|
+
class SentryAdapter {
|
|
3
|
+
category;
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.category = config?.category ?? "smrt";
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Handle a signal by routing to Sentry
|
|
9
|
+
*
|
|
10
|
+
* Error signals are captured as exceptions. All other signal types
|
|
11
|
+
* are added as breadcrumbs.
|
|
12
|
+
*
|
|
13
|
+
* @param signal - The signal to handle
|
|
14
|
+
*/
|
|
15
|
+
async handle(signal) {
|
|
16
|
+
if (signal.type === "error") {
|
|
17
|
+
this.captureError(signal);
|
|
18
|
+
} else {
|
|
19
|
+
this.addBreadcrumb(signal);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
captureError(signal) {
|
|
23
|
+
const error = signal.error ?? new Error("Unknown SMRT error");
|
|
24
|
+
Sentry.withScope((scope) => {
|
|
25
|
+
scope.setTag("smrt.class", signal.className);
|
|
26
|
+
scope.setTag("smrt.method", signal.method);
|
|
27
|
+
scope.setContext("smrt", {
|
|
28
|
+
signalId: signal.id,
|
|
29
|
+
objectId: signal.objectId,
|
|
30
|
+
duration: signal.duration,
|
|
31
|
+
...signal.metadata
|
|
32
|
+
});
|
|
33
|
+
Sentry.captureException(error);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
addBreadcrumb(signal) {
|
|
37
|
+
const levelMap = {
|
|
38
|
+
start: "debug",
|
|
39
|
+
step: "debug",
|
|
40
|
+
end: "info",
|
|
41
|
+
error: "error"
|
|
42
|
+
};
|
|
43
|
+
let message;
|
|
44
|
+
switch (signal.type) {
|
|
45
|
+
case "start":
|
|
46
|
+
message = `${signal.className}.${signal.method}() started`;
|
|
47
|
+
break;
|
|
48
|
+
case "step":
|
|
49
|
+
message = `${signal.className}.${signal.method}() step: ${signal.step || "unknown"}`;
|
|
50
|
+
break;
|
|
51
|
+
case "end":
|
|
52
|
+
message = `${signal.className}.${signal.method}() completed in ${signal.duration}ms`;
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
message = `${signal.className}.${signal.method}() ${signal.type}`;
|
|
56
|
+
}
|
|
57
|
+
Sentry.addBreadcrumb({
|
|
58
|
+
category: this.category,
|
|
59
|
+
message,
|
|
60
|
+
level: levelMap[signal.type] || "info",
|
|
61
|
+
data: {
|
|
62
|
+
signalId: signal.id,
|
|
63
|
+
objectId: signal.objectId,
|
|
64
|
+
className: signal.className,
|
|
65
|
+
method: signal.method,
|
|
66
|
+
...signal.duration !== void 0 && { duration: signal.duration },
|
|
67
|
+
...signal.metadata
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function createSentryAdapter(config) {
|
|
73
|
+
return new SentryAdapter(config);
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
SentryAdapter,
|
|
77
|
+
createSentryAdapter
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=sentry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry.js","sources":["../src/sentry-adapter.ts"],"sourcesContent":["/**\n * Sentry signal adapter for error tracking\n *\n * Routes SMRT framework signals to Sentry/GlitchTip:\n * - Error signals → Sentry.captureException with scope tags and context\n * - Non-error signals → Sentry.addBreadcrumb for debugging trail\n *\n * Consumer must install @sentry/node and call Sentry.init() before use.\n */\n\nimport * as Sentry from '@sentry/node';\nimport type { Signal, SignalAdapter } from './signal-types.js';\n\n/**\n * Configuration for the Sentry signal adapter\n */\nexport interface SentryAdapterConfig {\n /** Breadcrumb category (default: 'smrt') */\n category?: string;\n}\n\n/**\n * Sentry signal adapter — routes SMRT signals to Sentry/GlitchTip\n *\n * Error signals are captured as exceptions with scope tags and context.\n * All other signal types are added as breadcrumbs for debugging trail.\n * Requires `@sentry/node` to be installed and `Sentry.init()` called before use.\n *\n * @example\n * ```typescript\n * import { createSentryAdapter } from '@happyvertical/logger/sentry';\n *\n * const adapter = createSentryAdapter({ category: 'myapp' });\n * ```\n */\nexport class SentryAdapter implements SignalAdapter {\n private category: string;\n\n constructor(config?: SentryAdapterConfig) {\n this.category = config?.category ?? 'smrt';\n }\n\n /**\n * Handle a signal by routing to Sentry\n *\n * Error signals are captured as exceptions. All other signal types\n * are added as breadcrumbs.\n *\n * @param signal - The signal to handle\n */\n async handle(signal: Signal): Promise<void> {\n if (signal.type === 'error') {\n this.captureError(signal);\n } else {\n this.addBreadcrumb(signal);\n }\n }\n\n private captureError(signal: Signal): void {\n const error = signal.error ?? new Error('Unknown SMRT error');\n\n Sentry.withScope((scope) => {\n scope.setTag('smrt.class', signal.className);\n scope.setTag('smrt.method', signal.method);\n\n scope.setContext('smrt', {\n signalId: signal.id,\n objectId: signal.objectId,\n duration: signal.duration,\n ...signal.metadata,\n });\n\n Sentry.captureException(error);\n });\n }\n\n private addBreadcrumb(signal: Signal): void {\n const levelMap: Record<string, Sentry.SeverityLevel> = {\n start: 'debug',\n step: 'debug',\n end: 'info',\n error: 'error',\n };\n\n let message: string;\n switch (signal.type) {\n case 'start':\n message = `${signal.className}.${signal.method}() started`;\n break;\n case 'step':\n message = `${signal.className}.${signal.method}() step: ${signal.step || 'unknown'}`;\n break;\n case 'end':\n message = `${signal.className}.${signal.method}() completed in ${signal.duration}ms`;\n break;\n default:\n message = `${signal.className}.${signal.method}() ${signal.type}`;\n }\n\n Sentry.addBreadcrumb({\n category: this.category,\n message,\n level: levelMap[signal.type] || 'info',\n data: {\n signalId: signal.id,\n objectId: signal.objectId,\n className: signal.className,\n method: signal.method,\n ...(signal.duration !== undefined && { duration: signal.duration }),\n ...signal.metadata,\n },\n });\n }\n}\n\n/**\n * Create a Sentry signal adapter\n *\n * @param config - Optional configuration (breadcrumb category)\n * @returns Configured SentryAdapter instance\n */\nexport function createSentryAdapter(\n config?: SentryAdapterConfig,\n): SentryAdapter {\n return new SentryAdapter(config);\n}\n"],"names":[],"mappings":";AAmCO,MAAM,cAAuC;AAAA,EAC1C;AAAA,EAER,YAAY,QAA8B;AACxC,SAAK,WAAW,QAAQ,YAAY;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,OAAO,QAA+B;AAC1C,QAAI,OAAO,SAAS,SAAS;AAC3B,WAAK,aAAa,MAAM;AAAA,IAC1B,OAAO;AACL,WAAK,cAAc,MAAM;AAAA,IAC3B;AAAA,EACF;AAAA,EAEQ,aAAa,QAAsB;AACzC,UAAM,QAAQ,OAAO,SAAS,IAAI,MAAM,oBAAoB;AAE5D,WAAO,UAAU,CAAC,UAAU;AAC1B,YAAM,OAAO,cAAc,OAAO,SAAS;AAC3C,YAAM,OAAO,eAAe,OAAO,MAAM;AAEzC,YAAM,WAAW,QAAQ;AAAA,QACvB,UAAU,OAAO;AAAA,QACjB,UAAU,OAAO;AAAA,QACjB,UAAU,OAAO;AAAA,QACjB,GAAG,OAAO;AAAA,MAAA,CACX;AAED,aAAO,iBAAiB,KAAK;AAAA,IAC/B,CAAC;AAAA,EACH;AAAA,EAEQ,cAAc,QAAsB;AAC1C,UAAM,WAAiD;AAAA,MACrD,OAAO;AAAA,MACP,MAAM;AAAA,MACN,KAAK;AAAA,MACL,OAAO;AAAA,IAAA;AAGT,QAAI;AACJ,YAAQ,OAAO,MAAA;AAAA,MACb,KAAK;AACH,kBAAU,GAAG,OAAO,SAAS,IAAI,OAAO,MAAM;AAC9C;AAAA,MACF,KAAK;AACH,kBAAU,GAAG,OAAO,SAAS,IAAI,OAAO,MAAM,YAAY,OAAO,QAAQ,SAAS;AAClF;AAAA,MACF,KAAK;AACH,kBAAU,GAAG,OAAO,SAAS,IAAI,OAAO,MAAM,mBAAmB,OAAO,QAAQ;AAChF;AAAA,MACF;AACE,kBAAU,GAAG,OAAO,SAAS,IAAI,OAAO,MAAM,MAAM,OAAO,IAAI;AAAA,IAAA;AAGnE,WAAO,cAAc;AAAA,MACnB,UAAU,KAAK;AAAA,MACf;AAAA,MACA,OAAO,SAAS,OAAO,IAAI,KAAK;AAAA,MAChC,MAAM;AAAA,QACJ,UAAU,OAAO;AAAA,QACjB,UAAU,OAAO;AAAA,QACjB,WAAW,OAAO;AAAA,QAClB,QAAQ,OAAO;AAAA,QACf,GAAI,OAAO,aAAa,UAAa,EAAE,UAAU,OAAO,SAAA;AAAA,QACxD,GAAG,OAAO;AAAA,MAAA;AAAA,IACZ,CACD;AAAA,EACH;AACF;AAQO,SAAS,oBACd,QACe;AACf,SAAO,IAAI,cAAc,MAAM;AACjC;"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local Signal type definitions for logger adapter
|
|
3
|
+
* These types are copied from @happyvertical/types to keep logger independent
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Signal types representing different phases of operation execution
|
|
7
|
+
*/
|
|
8
|
+
export type SignalType = 'start' | 'step' | 'end' | 'error';
|
|
9
|
+
/**
|
|
10
|
+
* Signal - Represents an event in operation execution
|
|
11
|
+
*/
|
|
12
|
+
export interface Signal {
|
|
13
|
+
/** Unique signal ID */
|
|
14
|
+
id: string;
|
|
15
|
+
/** Signal type */
|
|
16
|
+
type: SignalType;
|
|
17
|
+
/** Object ID that emitted the signal */
|
|
18
|
+
objectId: string;
|
|
19
|
+
/** Class name of the emitting object */
|
|
20
|
+
className: string;
|
|
21
|
+
/** Method name that emitted the signal */
|
|
22
|
+
method: string;
|
|
23
|
+
/** Timestamp when signal was emitted */
|
|
24
|
+
timestamp: Date;
|
|
25
|
+
/** Step description (for 'step' type signals) */
|
|
26
|
+
step?: string;
|
|
27
|
+
/** Operation duration in milliseconds (for 'end' type signals) */
|
|
28
|
+
duration?: number;
|
|
29
|
+
/** Operation result (for 'end' type signals) */
|
|
30
|
+
result?: unknown;
|
|
31
|
+
/** Error information (for 'error' type signals) */
|
|
32
|
+
error?: Error;
|
|
33
|
+
/** Additional metadata */
|
|
34
|
+
metadata?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Signal Adapter interface - Handles signals for various purposes
|
|
38
|
+
*/
|
|
39
|
+
export interface SignalAdapter {
|
|
40
|
+
/**
|
|
41
|
+
* Handle a signal
|
|
42
|
+
* @param signal - The signal to handle
|
|
43
|
+
*/
|
|
44
|
+
handle(signal: Signal): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=signal-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-types.d.ts","sourceRoot":"","sources":["../src/signal-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,kBAAkB;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,SAAS,EAAE,IAAI,CAAC;IAChB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Logger, LogLevel } from './logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Log entry captured by TestLogger
|
|
4
|
+
*/
|
|
5
|
+
export interface LogEntry {
|
|
6
|
+
level: LogLevel;
|
|
7
|
+
message: string;
|
|
8
|
+
context?: Record<string, unknown>;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Test logger that captures log entries in memory
|
|
13
|
+
*
|
|
14
|
+
* Useful for testing code that uses loggers without:
|
|
15
|
+
* - Mocking logger methods with vi.fn()
|
|
16
|
+
* - Spying on console output
|
|
17
|
+
* - Writing to actual log files
|
|
18
|
+
*
|
|
19
|
+
* Provides a real Logger implementation that can be inspected in tests.
|
|
20
|
+
*/
|
|
21
|
+
export declare class TestLogger implements Logger {
|
|
22
|
+
/**
|
|
23
|
+
* All log entries captured by this logger
|
|
24
|
+
*/
|
|
25
|
+
readonly entries: LogEntry[];
|
|
26
|
+
/**
|
|
27
|
+
* Minimum log level to capture (optional filtering)
|
|
28
|
+
*/
|
|
29
|
+
private level?;
|
|
30
|
+
constructor(level?: LogLevel);
|
|
31
|
+
/**
|
|
32
|
+
* Get entries of a specific level
|
|
33
|
+
*/
|
|
34
|
+
getEntriesByLevel(level: LogLevel): LogEntry[];
|
|
35
|
+
/**
|
|
36
|
+
* Get the most recent entry
|
|
37
|
+
*/
|
|
38
|
+
getLastEntry(): LogEntry | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Check if a log level should be captured
|
|
41
|
+
*/
|
|
42
|
+
private shouldLog;
|
|
43
|
+
/**
|
|
44
|
+
* Capture a log entry
|
|
45
|
+
*/
|
|
46
|
+
private log;
|
|
47
|
+
/**
|
|
48
|
+
* Clear all captured entries
|
|
49
|
+
*/
|
|
50
|
+
clear(): void;
|
|
51
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
52
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
53
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
54
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=test-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-logger.d.ts","sourceRoot":"","sources":["../src/test-logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,qBAAa,UAAW,YAAW,MAAM;IACvC;;OAEG;IACH,SAAgB,OAAO,EAAE,QAAQ,EAAE,CAAM;IAEzC;;OAEG;IACH,OAAO,CAAC,KAAK,CAAC,CAAW;gBAEb,KAAK,CAAC,EAAE,QAAQ;IAI5B;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ,EAAE;IAI9C;;OAEG;IACH,YAAY,IAAI,QAAQ,GAAG,SAAS;IAIpC;;OAEG;IACH,OAAO,CAAC,SAAS;IASjB;;OAEG;IACH,OAAO,CAAC,GAAG;IAeX;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGhE"}
|
package/metadata.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@happyvertical/logger",
|
|
3
|
+
"path": "packages/logger",
|
|
4
|
+
"position": {
|
|
5
|
+
"index": 18,
|
|
6
|
+
"count": 30
|
|
7
|
+
},
|
|
8
|
+
"description": "Structured logging for HAVE SDK with signal adapter",
|
|
9
|
+
"provides": [
|
|
10
|
+
"Structured logging for HAVE SDK with signal adapter"
|
|
11
|
+
],
|
|
12
|
+
"implements": [],
|
|
13
|
+
"requires": {
|
|
14
|
+
"workspace": [
|
|
15
|
+
"@happyvertical/utils"
|
|
16
|
+
],
|
|
17
|
+
"externalHappyVertical": [],
|
|
18
|
+
"external": [
|
|
19
|
+
"@sentry/node"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"dependents": [
|
|
23
|
+
"@happyvertical/comfyui",
|
|
24
|
+
"@happyvertical/email",
|
|
25
|
+
"@happyvertical/encryption",
|
|
26
|
+
"@happyvertical/messages",
|
|
27
|
+
"@happyvertical/social",
|
|
28
|
+
"@happyvertical/video"
|
|
29
|
+
],
|
|
30
|
+
"stability": {
|
|
31
|
+
"level": "stable",
|
|
32
|
+
"reason": "Primary package surface is described as implemented and production-oriented."
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"logger"
|
|
36
|
+
]
|
|
37
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@happyvertical/logger",
|
|
3
|
+
"version": "0.74.8",
|
|
4
|
+
"description": "Structured logging for HAVE SDK with signal adapter",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./sentry": {
|
|
14
|
+
"import": "./dist/sentry.js",
|
|
15
|
+
"types": "./dist/sentry.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@sentry/node": ">=10.49.0"
|
|
20
|
+
},
|
|
21
|
+
"peerDependenciesMeta": {
|
|
22
|
+
"@sentry/node": {
|
|
23
|
+
"optional": true
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"bin": {
|
|
27
|
+
"have-logger-context": "./dist/cli/claude-context.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE",
|
|
33
|
+
"AGENT.md",
|
|
34
|
+
"metadata.json"
|
|
35
|
+
],
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"registry": "https://registry.npmjs.org",
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@happyvertical/utils": "0.74.8"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@sentry/node": "^10.49.0",
|
|
45
|
+
"@types/node": "25.0.10",
|
|
46
|
+
"typescript": "^5.9.3",
|
|
47
|
+
"vite": "7.3.2",
|
|
48
|
+
"vitest": "^4.1.5"
|
|
49
|
+
},
|
|
50
|
+
"keywords": [
|
|
51
|
+
"logging",
|
|
52
|
+
"structured-logging",
|
|
53
|
+
"signals",
|
|
54
|
+
"observability",
|
|
55
|
+
"have-sdk"
|
|
56
|
+
],
|
|
57
|
+
"repository": {
|
|
58
|
+
"type": "git",
|
|
59
|
+
"url": "https://github.com/happyvertical/sdk.git",
|
|
60
|
+
"directory": "packages/logger"
|
|
61
|
+
},
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/happyvertical/sdk/issues"
|
|
64
|
+
},
|
|
65
|
+
"homepage": "https://github.com/happyvertical/sdk/tree/main/packages/logger#readme",
|
|
66
|
+
"license": "MIT",
|
|
67
|
+
"scripts": {
|
|
68
|
+
"build": "vite build",
|
|
69
|
+
"dev": "vite build --watch",
|
|
70
|
+
"test": "vitest run",
|
|
71
|
+
"test:watch": "vitest",
|
|
72
|
+
"typecheck": "tsc --noEmit"
|
|
73
|
+
}
|
|
74
|
+
}
|