47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
import {randomId} from "@welshman/lib"
|
|
import {WrappedSigner} from "@welshman/signer"
|
|
import type {ISigner} from "@welshman/signer"
|
|
|
|
/**
|
|
* A structured, extensible log event. The built-in `signer` variant tracks each
|
|
* signer operation (sign/encrypt/decrypt/getPubkey); the open variant lets
|
|
* callers emit their own event types — it's not just a string.
|
|
*/
|
|
export type LogMessage =
|
|
| {
|
|
type: "signer"
|
|
id: string
|
|
method: string
|
|
status: "pending" | "success" | "failure"
|
|
error?: unknown
|
|
at: number
|
|
}
|
|
| {type: string; at: number; [key: string]: unknown}
|
|
|
|
/**
|
|
* An `ISigner` wrapper that emits a structured `LogMessage` (as a "message"
|
|
* event on itself) for every operation it performs. `User.fromSigner` wraps
|
|
* signers in this so they're observable; subscribe via `makeAppPolicyLogger`.
|
|
*/
|
|
export class LoggingSigner extends WrappedSigner {
|
|
constructor(signer: ISigner) {
|
|
super(signer, async (method, thunk) => {
|
|
const id = randomId()
|
|
|
|
this.emit("message", {type: "signer", id, method, status: "pending", at: Date.now()})
|
|
|
|
try {
|
|
const result = await thunk()
|
|
|
|
this.emit("message", {type: "signer", id, method, status: "success", at: Date.now()})
|
|
|
|
return result
|
|
} catch (error) {
|
|
this.emit("message", {type: "signer", id, method, status: "failure", error, at: Date.now()})
|
|
|
|
throw error
|
|
}
|
|
})
|
|
}
|
|
}
|