@happyvertical/logger 0.80.0 → 0.80.2
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/dist/cli/claude-context.js +17 -17
- package/dist/cli/claude-context.js.map +1 -1
- package/dist/index.js +183 -152
- package/dist/index.js.map +1 -1
- package/dist/sentry.js +101 -76
- package/dist/sentry.js.map +1 -1
- package/package.json +5 -5
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { existsSync, mkdirSync
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
if (existsSync(metaSrc)) {
|
|
18
|
-
copyFileSync(metaSrc, join(targetDir, `have-${pkgName}.meta.json`));
|
|
19
|
-
}
|
|
5
|
+
//#region src/cli/claude-context.ts
|
|
6
|
+
/**
|
|
7
|
+
* CLI script to install agent context for @happyvertical/logger
|
|
8
|
+
* Run the published context installer binary for this package.
|
|
9
|
+
*/
|
|
10
|
+
var pkgRoot = join(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
11
|
+
var targetDir = join(process.cwd(), ".claude");
|
|
12
|
+
if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
|
|
13
|
+
var pkgName = "logger";
|
|
14
|
+
var agentMdSrc = existsSync(join(pkgRoot, "AGENT.md")) ? join(pkgRoot, "AGENT.md") : join(pkgRoot, "CLAUDE.md");
|
|
15
|
+
var metaSrc = existsSync(join(pkgRoot, "metadata.json")) ? join(pkgRoot, "metadata.json") : join(pkgRoot, ".claude-meta.json");
|
|
16
|
+
if (existsSync(agentMdSrc)) copyFileSync(agentMdSrc, join(targetDir, `have-${pkgName}.md`));
|
|
17
|
+
if (existsSync(metaSrc)) copyFileSync(metaSrc, join(targetDir, `have-${pkgName}.meta.json`));
|
|
20
18
|
console.log(`✓ Installed @happyvertical/${pkgName} context to .claude/`);
|
|
21
|
-
//#
|
|
19
|
+
//#endregion
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=claude-context.js.map
|
|
@@ -1 +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"],"
|
|
1
|
+
{"version":3,"file":"claude-context.js","names":[],"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"],"mappings":";;;;;;;;;AAUA,IAAM,UAAU,KADA,QAAQ,cAAc,OAAO,KAAK,GAAG,CAChC,GAAS,OAAO;AACrC,IAAM,YAAY,KAAK,QAAQ,IAAI,GAAG,SAAS;AAE/C,IAAI,CAAC,WAAW,SAAS,GACvB,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAG1C,IAAM,UAAU;AAChB,IAAM,aAAa,WAAW,KAAK,SAAS,UAAU,CAAC,IACnD,KAAK,SAAS,UAAU,IACxB,KAAK,SAAS,WAAW;AAC7B,IAAM,UAAU,WAAW,KAAK,SAAS,eAAe,CAAC,IACrD,KAAK,SAAS,eAAe,IAC7B,KAAK,SAAS,mBAAmB;AAErC,IAAI,WAAW,UAAU,GACvB,aAAa,YAAY,KAAK,WAAW,QAAQ,QAAQ,IAAI,CAAC;AAGhE,IAAI,WAAW,OAAO,GACpB,aAAa,SAAS,KAAK,WAAW,QAAQ,QAAQ,WAAW,CAAC;AAGpE,QAAQ,IAAI,8BAA8B,QAAQ,qBAAqB"}
|
package/dist/index.js
CHANGED
|
@@ -1,155 +1,186 @@
|
|
|
1
1
|
import { loadEnvConfig } from "@happyvertical/utils";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
2
|
+
//#region src/adapter.ts
|
|
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
|
+
var LoggerAdapter = class {
|
|
21
|
+
logger;
|
|
22
|
+
constructor(logger) {
|
|
23
|
+
this.logger = logger;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Handle a signal and log appropriately
|
|
27
|
+
*
|
|
28
|
+
* @param signal - Signal to log
|
|
29
|
+
*/
|
|
30
|
+
async handle(signal) {
|
|
31
|
+
const context = {
|
|
32
|
+
id: signal.id,
|
|
33
|
+
objectId: signal.objectId,
|
|
34
|
+
className: signal.className,
|
|
35
|
+
method: signal.method,
|
|
36
|
+
timestamp: signal.timestamp
|
|
37
|
+
};
|
|
38
|
+
if (signal.duration !== void 0) context.duration = signal.duration;
|
|
39
|
+
if (signal.metadata) context.metadata = signal.metadata;
|
|
40
|
+
switch (signal.type) {
|
|
41
|
+
case "start":
|
|
42
|
+
this.logger.debug(`${signal.className}.${signal.method}() started`, context);
|
|
43
|
+
break;
|
|
44
|
+
case "step":
|
|
45
|
+
this.logger.debug(`${signal.className}.${signal.method}() step: ${signal.step || "unknown"}`, context);
|
|
46
|
+
break;
|
|
47
|
+
case "end":
|
|
48
|
+
this.logger.info(`${signal.className}.${signal.method}() completed in ${signal.duration}ms`, {
|
|
49
|
+
...context,
|
|
50
|
+
result: signal.result !== void 0 ? "present" : "none"
|
|
51
|
+
});
|
|
52
|
+
break;
|
|
53
|
+
case "error":
|
|
54
|
+
this.logger.error(`${signal.className}.${signal.method}() failed: ${signal.error?.message || "Unknown error"}`, {
|
|
55
|
+
...context,
|
|
56
|
+
error: signal.error ? {
|
|
57
|
+
message: signal.error.message,
|
|
58
|
+
name: signal.error.name,
|
|
59
|
+
stack: signal.error.stack
|
|
60
|
+
} : void 0
|
|
61
|
+
});
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/console.ts
|
|
68
|
+
/**
|
|
69
|
+
* Console-based logger with level filtering
|
|
70
|
+
*
|
|
71
|
+
* Logs are written to console with appropriate severity levels.
|
|
72
|
+
* Messages are only output if they meet the configured log level threshold.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const logger = new ConsoleLogger('info');
|
|
77
|
+
* logger.debug('Debug message'); // Not output (below 'info')
|
|
78
|
+
* logger.info('Info message'); // Output
|
|
79
|
+
* logger.error('Error message'); // Output
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
var ConsoleLogger = class ConsoleLogger {
|
|
83
|
+
level;
|
|
84
|
+
static LEVELS = [
|
|
85
|
+
"debug",
|
|
86
|
+
"info",
|
|
87
|
+
"warn",
|
|
88
|
+
"error"
|
|
89
|
+
];
|
|
90
|
+
constructor(level = "info") {
|
|
91
|
+
this.level = level;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Check if a log level should be output
|
|
95
|
+
*
|
|
96
|
+
* @param level - Log level to check
|
|
97
|
+
* @returns True if level meets threshold
|
|
98
|
+
*/
|
|
99
|
+
shouldLog(level) {
|
|
100
|
+
const currentIndex = ConsoleLogger.LEVELS.indexOf(this.level);
|
|
101
|
+
return ConsoleLogger.LEVELS.indexOf(level) >= currentIndex;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Format context for console output
|
|
105
|
+
*
|
|
106
|
+
* @param context - Structured metadata
|
|
107
|
+
* @returns Formatted context string
|
|
108
|
+
*/
|
|
109
|
+
formatContext(context) {
|
|
110
|
+
if (!context || Object.keys(context).length === 0) return "";
|
|
111
|
+
return ` ${JSON.stringify(context)}`;
|
|
112
|
+
}
|
|
113
|
+
debug(message, context) {
|
|
114
|
+
if (this.shouldLog("debug")) console.debug(`[DEBUG] ${message}${this.formatContext(context)}`);
|
|
115
|
+
}
|
|
116
|
+
info(message, context) {
|
|
117
|
+
if (this.shouldLog("info")) console.info(`[INFO] ${message}${this.formatContext(context)}`);
|
|
118
|
+
}
|
|
119
|
+
warn(message, context) {
|
|
120
|
+
if (this.shouldLog("warn")) console.warn(`[WARN] ${message}${this.formatContext(context)}`);
|
|
121
|
+
}
|
|
122
|
+
error(message, context) {
|
|
123
|
+
if (this.shouldLog("error")) console.error(`[ERROR] ${message}${this.formatContext(context)}`);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/index.ts
|
|
128
|
+
/**
|
|
129
|
+
* No-op logger that discards all log messages
|
|
130
|
+
*
|
|
131
|
+
* Used when logging is disabled (config: false)
|
|
132
|
+
*/
|
|
133
|
+
var NoopLogger = class {
|
|
134
|
+
debug(_message, _context) {}
|
|
135
|
+
info(_message, _context) {}
|
|
136
|
+
warn(_message, _context) {}
|
|
137
|
+
error(_message, _context) {}
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Create a logger from configuration
|
|
141
|
+
*
|
|
142
|
+
* Supports environment variable configuration via HAVE_LOGGER_LEVEL.
|
|
143
|
+
* User-provided options take precedence over environment variables.
|
|
144
|
+
*
|
|
145
|
+
* @param config - Logger configuration (boolean or object)
|
|
146
|
+
* @returns Configured logger instance
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* // Console logger with 'info' level (default)
|
|
151
|
+
* const logger1 = createLogger(true);
|
|
152
|
+
*
|
|
153
|
+
* // Console logger with level from HAVE_LOGGER_LEVEL env var
|
|
154
|
+
* process.env.HAVE_LOGGER_LEVEL = 'debug';
|
|
155
|
+
* const logger2 = createLogger(true); // Uses 'debug' from env
|
|
156
|
+
*
|
|
157
|
+
* // No-op logger (all log calls are discarded)
|
|
158
|
+
* const logger3 = createLogger(false);
|
|
159
|
+
*
|
|
160
|
+
* // Console logger with 'debug' level (overrides env)
|
|
161
|
+
* const logger4 = createLogger({ level: 'debug' });
|
|
162
|
+
*
|
|
163
|
+
* // Custom log level (user options take precedence)
|
|
164
|
+
* process.env.HAVE_LOGGER_LEVEL = 'info';
|
|
165
|
+
* const logger5 = createLogger({ level: 'warn' }); // Uses 'warn' not 'info'
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
127
168
|
function createLogger(config) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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);
|
|
169
|
+
if (typeof config === "boolean") {
|
|
170
|
+
if (!config) return new NoopLogger();
|
|
171
|
+
return new ConsoleLogger(loadEnvConfig({}, {
|
|
172
|
+
packageName: "logger",
|
|
173
|
+
schema: { level: "string" }
|
|
174
|
+
}).level || "info");
|
|
175
|
+
}
|
|
176
|
+
return new ConsoleLogger(loadEnvConfig(config, {
|
|
177
|
+
packageName: "logger",
|
|
178
|
+
schema: { level: "string" }
|
|
179
|
+
}).level || "info");
|
|
147
180
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
};
|
|
155
|
-
//# sourceMappingURL=index.js.map
|
|
181
|
+
/** @internal */
|
|
182
|
+
var PACKAGE_VERSION_INITIALIZED = true;
|
|
183
|
+
//#endregion
|
|
184
|
+
export { ConsoleLogger, LoggerAdapter, PACKAGE_VERSION_INITIALIZED, createLogger };
|
|
185
|
+
|
|
186
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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":";AAwBO,MAAM,cAAuC;AAAA,EAClD,YAAoB,QAAgB;AAAhB,SAAA,SAAA;AAAA,EAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,MAAM,OAAO,QAA+B;AAC1C,UAAM,UAAmC;AAAA,MACvC,IAAI,OAAO;AAAA,MACX,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,MAClB,QAAQ,OAAO;AAAA,MACf,WAAW,OAAO;AAAA,IAAA;AAIpB,QAAI,OAAO,aAAa,QAAW;AACjC,cAAQ,WAAW,OAAO;AAAA,IAC5B;AAEA,QAAI,OAAO,UAAU;AACnB,cAAQ,WAAW,OAAO;AAAA,IAC5B;AAEA,YAAQ,OAAO,MAAA;AAAA,MACb,KAAK;AACH,aAAK,OAAO;AAAA,UACV,GAAG,OAAO,SAAS,IAAI,OAAO,MAAM;AAAA,UACpC;AAAA,QAAA;AAEF;AAAA,MAEF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,GAAG,OAAO,SAAS,IAAI,OAAO,MAAM,YAAY,OAAO,QAAQ,SAAS;AAAA,UACxE;AAAA,QAAA;AAEF;AAAA,MAEF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,GAAG,OAAO,SAAS,IAAI,OAAO,MAAM,mBAAmB,OAAO,QAAQ;AAAA,UACtE;AAAA,YACE,GAAG;AAAA,YACH,QAAQ,OAAO,WAAW,SAAY,YAAY;AAAA,UAAA;AAAA,QACpD;AAEF;AAAA,MAEF,KAAK;AACH,aAAK,OAAO;AAAA,UACV,GAAG,OAAO,SAAS,IAAI,OAAO,MAAM,cAAc,OAAO,OAAO,WAAW,eAAe;AAAA,UAC1F;AAAA,YACE,GAAG;AAAA,YACH,OAAO,OAAO,QACV;AAAA,cACE,SAAS,OAAO,MAAM;AAAA,cACtB,MAAM,OAAO,MAAM;AAAA,cACnB,OAAO,OAAO,MAAM;AAAA,YAAA,IAEtB;AAAA,UAAA;AAAA,QACN;AAEF;AAAA,IAAA;AAAA,EAEN;AACF;ACxEO,MAAM,cAAgC;AAAA,EAQ3C,YAAoB,QAAkB,QAAQ;AAA1B,SAAA,QAAA;AAAA,EAA2B;AAAA,EAP/C,OAAwB,SAAkC;AAAA,IACxD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWM,UAAU,OAA0B;AAC1C,UAAM,eAAe,cAAc,OAAO,QAAQ,KAAK,KAAK;AAC5D,UAAM,eAAe,cAAc,OAAO,QAAQ,KAAK;AACvD,WAAO,gBAAgB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,cAAc,SAA2C;AAC/D,QAAI,CAAC,WAAW,OAAO,KAAK,OAAO,EAAE,WAAW,GAAG;AACjD,aAAO;AAAA,IACT;AACA,WAAO,IAAI,KAAK,UAAU,OAAO,CAAC;AAAA,EACpC;AAAA,EAEA,MAAM,SAAiB,SAAyC;AAC9D,QAAI,KAAK,UAAU,OAAO,GAAG;AAC3B,cAAQ,MAAM,WAAW,OAAO,GAAG,KAAK,cAAc,OAAO,CAAC,EAAE;AAAA,IAClE;AAAA,EACF;AAAA,EAEA,KAAK,SAAiB,SAAyC;AAC7D,QAAI,KAAK,UAAU,MAAM,GAAG;AAC1B,cAAQ,KAAK,UAAU,OAAO,GAAG,KAAK,cAAc,OAAO,CAAC,EAAE;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,KAAK,SAAiB,SAAyC;AAC7D,QAAI,KAAK,UAAU,MAAM,GAAG;AAC1B,cAAQ,KAAK,UAAU,OAAO,GAAG,KAAK,cAAc,OAAO,CAAC,EAAE;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,MAAM,SAAiB,SAAyC;AAC9D,QAAI,KAAK,UAAU,OAAO,GAAG;AAC3B,cAAQ,MAAM,WAAW,OAAO,GAAG,KAAK,cAAc,OAAO,CAAC,EAAE;AAAA,IAClE;AAAA,EACF;AACF;AC7CA,MAAM,WAA6B;AAAA,EACjC,MAAM,UAAkB,UAA0C;AAAA,EAElE;AAAA,EAEA,KAAK,UAAkB,UAA0C;AAAA,EAEjE;AAAA,EAEA,KAAK,UAAkB,UAA0C;AAAA,EAEjE;AAAA,EAEA,MAAM,UAAkB,UAA0C;AAAA,EAElE;AACF;AA+BO,SAAS,aAAa,QAA8B;AACzD,MAAI,OAAO,WAAW,WAAW;AAE/B,QAAI,CAAC,QAAQ;AACX,aAAO,IAAI,WAAA;AAAA,IACb;AAGA,UAAM,YAAY;AAAA,MAChB,CAAA;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,OAAO,SAAA;AAAA,MAAS;AAAA,IAC5B;AAGF,WAAO,IAAIA,cAAc,UAAU,SAAS,MAAM;AAAA,EACpD;AAGA,QAAM,eAAe,cAAoC,QAAQ;AAAA,IAC/D,aAAa;AAAA,IACb,QAAQ,EAAE,OAAO,SAAA;AAAA,EAAS,CAC3B;AAED,QAAM,QAAQ,aAAa,SAAS;AACpC,SAAO,IAAIA,cAAc,KAAK;AAChC;AAGO,MAAM,8BAA8B;"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"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"],"mappings":"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"}
|
package/dist/sentry.js
CHANGED
|
@@ -1,79 +1,104 @@
|
|
|
1
1
|
import * as Sentry from "@sentry/node";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
2
|
+
//#region src/sentry-adapter.ts
|
|
3
|
+
/**
|
|
4
|
+
* Sentry signal adapter for error tracking
|
|
5
|
+
*
|
|
6
|
+
* Routes SMRT framework signals to Sentry/GlitchTip:
|
|
7
|
+
* - Error signals → Sentry.captureException with scope tags and context
|
|
8
|
+
* - Non-error signals → Sentry.addBreadcrumb for debugging trail
|
|
9
|
+
*
|
|
10
|
+
* Consumer must install @sentry/node and call Sentry.init() before use.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Sentry signal adapter — routes SMRT signals to Sentry/GlitchTip
|
|
14
|
+
*
|
|
15
|
+
* Error signals are captured as exceptions with scope tags and context.
|
|
16
|
+
* All other signal types are added as breadcrumbs for debugging trail.
|
|
17
|
+
* Requires `@sentry/node` to be installed and `Sentry.init()` called before use.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { createSentryAdapter } from '@happyvertical/logger/sentry';
|
|
22
|
+
*
|
|
23
|
+
* const adapter = createSentryAdapter({ category: 'myapp' });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
var SentryAdapter = class {
|
|
27
|
+
category;
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.category = config?.category ?? "smrt";
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Handle a signal by routing to Sentry
|
|
33
|
+
*
|
|
34
|
+
* Error signals are captured as exceptions. All other signal types
|
|
35
|
+
* are added as breadcrumbs.
|
|
36
|
+
*
|
|
37
|
+
* @param signal - The signal to handle
|
|
38
|
+
*/
|
|
39
|
+
async handle(signal) {
|
|
40
|
+
if (signal.type === "error") this.captureError(signal);
|
|
41
|
+
else this.addBreadcrumb(signal);
|
|
42
|
+
}
|
|
43
|
+
captureError(signal) {
|
|
44
|
+
const error = signal.error ?? /* @__PURE__ */ new Error("Unknown SMRT error");
|
|
45
|
+
Sentry.withScope((scope) => {
|
|
46
|
+
scope.setTag("smrt.class", signal.className);
|
|
47
|
+
scope.setTag("smrt.method", signal.method);
|
|
48
|
+
scope.setContext("smrt", {
|
|
49
|
+
signalId: signal.id,
|
|
50
|
+
objectId: signal.objectId,
|
|
51
|
+
duration: signal.duration,
|
|
52
|
+
...signal.metadata
|
|
53
|
+
});
|
|
54
|
+
Sentry.captureException(error);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
addBreadcrumb(signal) {
|
|
58
|
+
const levelMap = {
|
|
59
|
+
start: "debug",
|
|
60
|
+
step: "debug",
|
|
61
|
+
end: "info",
|
|
62
|
+
error: "error"
|
|
63
|
+
};
|
|
64
|
+
let message;
|
|
65
|
+
switch (signal.type) {
|
|
66
|
+
case "start":
|
|
67
|
+
message = `${signal.className}.${signal.method}() started`;
|
|
68
|
+
break;
|
|
69
|
+
case "step":
|
|
70
|
+
message = `${signal.className}.${signal.method}() step: ${signal.step || "unknown"}`;
|
|
71
|
+
break;
|
|
72
|
+
case "end":
|
|
73
|
+
message = `${signal.className}.${signal.method}() completed in ${signal.duration}ms`;
|
|
74
|
+
break;
|
|
75
|
+
default: message = `${signal.className}.${signal.method}() ${signal.type}`;
|
|
76
|
+
}
|
|
77
|
+
Sentry.addBreadcrumb({
|
|
78
|
+
category: this.category,
|
|
79
|
+
message,
|
|
80
|
+
level: levelMap[signal.type] || "info",
|
|
81
|
+
data: {
|
|
82
|
+
signalId: signal.id,
|
|
83
|
+
objectId: signal.objectId,
|
|
84
|
+
className: signal.className,
|
|
85
|
+
method: signal.method,
|
|
86
|
+
...signal.duration !== void 0 && { duration: signal.duration },
|
|
87
|
+
...signal.metadata
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Create a Sentry signal adapter
|
|
94
|
+
*
|
|
95
|
+
* @param config - Optional configuration (breadcrumb category)
|
|
96
|
+
* @returns Configured SentryAdapter instance
|
|
97
|
+
*/
|
|
72
98
|
function createSentryAdapter(config) {
|
|
73
|
-
|
|
99
|
+
return new SentryAdapter(config);
|
|
74
100
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
//# sourceMappingURL=sentry.js.map
|
|
101
|
+
//#endregion
|
|
102
|
+
export { SentryAdapter, createSentryAdapter };
|
|
103
|
+
|
|
104
|
+
//# sourceMappingURL=sentry.js.map
|
package/dist/sentry.js.map
CHANGED
|
@@ -1 +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"],"
|
|
1
|
+
{"version":3,"file":"sentry.js","names":[],"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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,IAAa,gBAAb,MAAoD;CAClD;CAEA,YAAY,QAA8B;EACxC,KAAK,WAAW,QAAQ,YAAY;CACtC;;;;;;;;;CAUA,MAAM,OAAO,QAA+B;EAC1C,IAAI,OAAO,SAAS,SAClB,KAAK,aAAa,MAAM;OAExB,KAAK,cAAc,MAAM;CAE7B;CAEA,aAAqB,QAAsB;EACzC,MAAM,QAAQ,OAAO,yBAAS,IAAI,MAAM,oBAAoB;EAE5D,OAAO,WAAW,UAAU;GAC1B,MAAM,OAAO,cAAc,OAAO,SAAS;GAC3C,MAAM,OAAO,eAAe,OAAO,MAAM;GAEzC,MAAM,WAAW,QAAQ;IACvB,UAAU,OAAO;IACjB,UAAU,OAAO;IACjB,UAAU,OAAO;IACjB,GAAG,OAAO;GACZ,CAAC;GAED,OAAO,iBAAiB,KAAK;EAC/B,CAAC;CACH;CAEA,cAAsB,QAAsB;EAC1C,MAAM,WAAiD;GACrD,OAAO;GACP,MAAM;GACN,KAAK;GACL,OAAO;EACT;EAEA,IAAI;EACJ,QAAQ,OAAO,MAAf;GACE,KAAK;IACH,UAAU,GAAG,OAAO,UAAU,GAAG,OAAO,OAAO;IAC/C;GACF,KAAK;IACH,UAAU,GAAG,OAAO,UAAU,GAAG,OAAO,OAAO,WAAW,OAAO,QAAQ;IACzE;GACF,KAAK;IACH,UAAU,GAAG,OAAO,UAAU,GAAG,OAAO,OAAO,kBAAkB,OAAO,SAAS;IACjF;GACF,SACE,UAAU,GAAG,OAAO,UAAU,GAAG,OAAO,OAAO,KAAK,OAAO;EAC/D;EAEA,OAAO,cAAc;GACnB,UAAU,KAAK;GACf;GACA,OAAO,SAAS,OAAO,SAAS;GAChC,MAAM;IACJ,UAAU,OAAO;IACjB,UAAU,OAAO;IACjB,WAAW,OAAO;IAClB,QAAQ,OAAO;IACf,GAAI,OAAO,aAAa,KAAA,KAAa,EAAE,UAAU,OAAO,SAAS;IACjE,GAAG,OAAO;GACZ;EACF,CAAC;CACH;AACF;;;;;;;AAQA,SAAgB,oBACd,QACe;CACf,OAAO,IAAI,cAAc,MAAM;AACjC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/logger",
|
|
3
|
-
"version": "0.80.
|
|
3
|
+
"version": "0.80.2",
|
|
4
4
|
"description": "Structured logging for HAVE SDK with signal adapter",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,14 +38,14 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@happyvertical/utils": "0.80.
|
|
41
|
+
"@happyvertical/utils": "0.80.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@sentry/node": "^10.49.0",
|
|
45
45
|
"@types/node": "25.0.10",
|
|
46
|
-
"typescript": "
|
|
47
|
-
"vite": "
|
|
48
|
-
"vitest": "
|
|
46
|
+
"typescript": "5.9.3",
|
|
47
|
+
"vite": "8.1.4",
|
|
48
|
+
"vitest": "4.1.10"
|
|
49
49
|
},
|
|
50
50
|
"keywords": [
|
|
51
51
|
"logging",
|